示例#1
0
// Begins stack walking.
//
// Parameters:
//   stackStream    StackStream object
//   mode           Stack walking mode.
//   skip_frames    Number of frames to be skipped.
//   frame_count    Number of frames to be traversed.
//   start_index    Start index to the user-supplied buffers.
//   frames_array   Buffer to store 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.
//
// Returns Object returned from AbstractStackWalker::doStackWalk call.
//
oop StackWalk::walk(Handle stackStream, jlong mode,
                    int skip_frames, int frame_count, int start_index,
                    objArrayHandle frames_array,
                    TRAPS) {
    ResourceMark rm(THREAD);
    JavaThread* jt = (JavaThread*)THREAD;
    log_debug(stackwalk)("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d",
                         mode, skip_frames, frame_count);

    if (frames_array.is_null()) {
        THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
    }

    // Setup traversal onto my stack.
    if (live_frame_info(mode)) {
        assert (use_frames_array(mode), "Bad mode for get live frame");
        RegisterMap regMap(jt, true);
        LiveFrameStream stream(jt, &regMap);
        return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
                               start_index, frames_array, THREAD);
    } else {
        JavaFrameStream stream(jt, mode);
        return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
                               start_index, frames_array, THREAD);
    }
}
示例#2
0
// 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;
}
示例#3
0
// 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;
}