// Unpacks one or more frames into user-supplied buffers. // Updates the end index, and returns the number of unpacked frames. // Always start with the existing vfst.method and bci. // Do not call vfst.next to advance over the last returned value. // In other words, do not leave any stale data in the vfst. // // Parameters: // mode Restrict which frames to be decoded. // BaseFrameStream stream of frames // max_nframes Maximum number of frames to be filled. // start_index Start index to the user-supplied buffers. // frames_array Buffer to store Class or StackFrame in, starting at start_index. // frames array is a Class<?>[] array when only getting caller // reference, and a StackFrameInfo[] array (or derivative) // otherwise. It should never be null. // end_index End index to the user-supplied buffers with unpacked frames. // // Returns the number of frames whose information was transferred into the buffers. // int StackWalk::fill_in_frames(jlong mode, BaseFrameStream& stream, int max_nframes, int start_index, objArrayHandle frames_array, int& end_index, TRAPS) { log_debug(stackwalk)("fill_in_frames limit=%d start=%d frames length=%d", max_nframes, start_index, frames_array->length()); assert(max_nframes > 0, "invalid max_nframes"); assert(start_index + max_nframes <= frames_array->length(), "oob"); int frames_decoded = 0; for (; !stream.at_end(); stream.next()) { Method* method = stream.method(); if (method == NULL) continue; // skip hidden frames for default StackWalker option (i.e. SHOW_HIDDEN_FRAMES // not set) and when StackWalker::getCallerClass is called if (!ShowHiddenFrames && (skip_hidden_frames(mode) || get_caller_class(mode))) { if (method->is_hidden()) { if (log_is_enabled(Debug, stackwalk)) { ResourceMark rm(THREAD); outputStream* st = Log(stackwalk)::debug_stream(); st->print(" hidden method: "); method->print_short_name(st); st->cr(); } continue; } } int index = end_index++; if (log_is_enabled(Debug, stackwalk)) { ResourceMark rm(THREAD); outputStream* st = Log(stackwalk)::debug_stream(); st->print(" %d: frame method: ", index); method->print_short_name(st); st->print_cr(" bci=%d", stream.bci()); } if (!need_method_info(mode) && get_caller_class(mode) && index == start_index && method->caller_sensitive()) { ResourceMark rm(THREAD); THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method", method->name_and_sig_as_C_string())); } // fill in StackFrameInfo and initialize MemberName stream.fill_frame(index, frames_array, method, CHECK_0); if (++frames_decoded >= max_nframes) break; } return frames_decoded; }
// Unpacks one or more frames into user-supplied buffers. // Updates the end index, and returns the number of unpacked frames. // Always start with the existing vfst.method and bci. // Do not call vfst.next to advance over the last returned value. // In other words, do not leave any stale data in the vfst. // // Parameters: // mode Restrict which frames to be decoded. // JavaFrameStream stream of javaVFrames // max_nframes Maximum number of frames to be filled. // start_index Start index to the user-supplied buffers. // frames_array Buffer to store Class or StackFrame in, starting at start_index. // frames array is a Class<?>[] array when only getting caller // reference, and a StackFrameInfo[] array (or derivative) // otherwise. It should never be null. // end_index End index to the user-supplied buffers with unpacked frames. // // Returns the number of frames whose information was transferred into the buffers. // int StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream, int max_nframes, int start_index, objArrayHandle frames_array, int& end_index, TRAPS) { if (TraceStackWalk) { tty->print_cr("fill_in_frames limit=%d start=%d frames length=%d", max_nframes, start_index, frames_array->length()); } assert(max_nframes > 0, "invalid max_nframes"); assert(start_index + max_nframes <= frames_array->length(), "oob"); int frames_decoded = 0; for (; !stream.at_end(); stream.next()) { Method* method = stream.method(); int bci = stream.bci(); if (method == NULL) continue; if (!ShowHiddenFrames && StackWalk::skip_hidden_frames(mode)) { if (method->is_hidden()) { if (TraceStackWalk) { tty->print(" hidden method: "); method->print_short_name(); tty->print("\n"); } continue; } } int index = end_index++; if (TraceStackWalk) { tty->print(" %d: frame method: ", index); method->print_short_name(); tty->print_cr(" bci=%d", bci); } // fill in StackFrameInfo and initialize MemberName if (live_frame_info(mode)) { assert (use_frames_array(mode), "Bad mode for get live frame"); Handle stackFrame(frames_array->obj_at(index)); fill_live_stackframe(stackFrame, method, bci, stream.java_frame(), CHECK_0); } else if (need_method_info(mode)) { assert (use_frames_array(mode), "Bad mode for get stack frame"); Handle stackFrame(frames_array->obj_at(index)); fill_stackframe(stackFrame, method, bci); } else { assert (use_frames_array(mode) == false, "Bad mode for get caller class"); frames_array->obj_at_put(index, method->method_holder()->java_mirror()); } if (++frames_decoded >= max_nframes) break; } return frames_decoded; }
void Rewriter::relocate_and_link(instanceKlassHandle this_oop, objArrayHandle methods, TRAPS) { int len = methods->length(); for (int i = len-1; i >= 0; i--) { methodHandle m(THREAD, (methodOop)methods->obj_at(i)); if (m->has_jsrs()) { m = rewrite_jsrs(m, CHECK); // Method might have gotten rewritten. methods->obj_at_put(i, m()); } // Set up method entry points for compiler and interpreter . m->link_method(m, CHECK); // This is for JVMTI and unrelated to relocator but the last thing we do #ifdef ASSERT if (StressMethodComparator) { static int nmc = 0; for (int j = i; j >= 0 && j >= i-4; j--) { if ((++nmc % 1000) == 0) tty->print_cr("Have run MethodComparator %d times...", nmc); bool z = MethodComparator::methods_EMCP(m(), (methodOop)methods->obj_at(j)); if (j == i && !z) { tty->print("MethodComparator FAIL: "); m->print(); m->print_codes(); assert(z, "method must compare equal to itself"); } } } #endif //ASSERT } }
// Walk the next batch of stack frames // // Parameters: // stackStream StackStream object // mode Stack walking mode. // magic Must be valid value to continue the stack walk // frame_count Number of frames to be decoded. // start_index Start index to the user-supplied buffers. // classes_array Buffer to store classes in, starting at start_index. // frames_array Buffer to store StackFrame in, starting at start_index. // NULL if not used. // // Returns the end index of frame filled in the buffer. // jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, int frame_count, int start_index, objArrayHandle classes_array, objArrayHandle frames_array, TRAPS) { JavaThread* jt = (JavaThread*)THREAD; StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, classes_array); if (existing_anchor == NULL) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L); } if ((need_method_info(mode) || live_frame_info(mode)) && frames_array.is_null()) { THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L); } if (TraceStackWalk) { tty->print_cr("StackWalk::moreFrames frame_count %d existing_anchor " PTR_FORMAT " start %d frames %d", frame_count, p2i(existing_anchor), start_index, classes_array->length()); } int end_index = start_index; if (frame_count <= 0) { return end_index; // No operation. } int count = frame_count + start_index; assert (classes_array->length() >= count, "not enough space in buffers"); StackWalkAnchor& anchor = (*existing_anchor); vframeStream& vfst = anchor.vframe_stream(); if (!vfst.at_end()) { vfst.next(); // this was the last frame decoded in the previous batch if (!vfst.at_end()) { int n = fill_in_frames(mode, vfst, frame_count, start_index, classes_array, frames_array, end_index, CHECK_0); if (n < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L); } return end_index; } } return end_index; }
// Walk the next batch of stack frames // // Parameters: // stackStream StackStream object // mode Stack walking mode. // magic Must be valid value to continue the stack walk // frame_count Number of frames to be decoded. // start_index Start index to the user-supplied buffers. // frames_array Buffer to store StackFrame in, starting at start_index. // // Returns the end index of frame filled in the buffer. // jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic, int frame_count, int start_index, objArrayHandle frames_array, TRAPS) { JavaThread* jt = (JavaThread*)THREAD; JavaFrameStream* existing_stream = JavaFrameStream::from_current(jt, magic, frames_array); if (existing_stream == NULL) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L); } if (frames_array.is_null()) { THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L); } if (TraceStackWalk) { tty->print_cr("StackWalk::moreFrames frame_count %d existing_stream " PTR_FORMAT " start %d frames %d", frame_count, p2i(existing_stream), start_index, frames_array->length()); } int end_index = start_index; if (frame_count <= 0) { return end_index; // No operation. } int count = frame_count + start_index; assert (frames_array->length() >= count, "not enough space in buffers"); JavaFrameStream& stream = (*existing_stream); if (!stream.at_end()) { stream.next(); // advance past the last frame decoded in previous batch if (!stream.at_end()) { int n = fill_in_frames(mode, stream, frame_count, start_index, frames_array, end_index, CHECK_0); if (n < 1) { THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L); } return end_index; } } return end_index; }