hotspot/src/share/vm/prims/stackwalk.cpp
changeset 38213 2f32787e31b1
parent 37438 873c4aea8d1b
child 40001 f37246e66d2b
equal deleted inserted replaced
38198:8144ec8f789e 38213:2f32787e31b1
     1 /*
     1 /*
     2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2015, 2016 Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    35 #include "runtime/javaCalls.hpp"
    35 #include "runtime/javaCalls.hpp"
    36 #include "runtime/vframe.hpp"
    36 #include "runtime/vframe.hpp"
    37 #include "utilities/globalDefinitions.hpp"
    37 #include "utilities/globalDefinitions.hpp"
    38 
    38 
    39 // setup and cleanup actions
    39 // setup and cleanup actions
    40 void StackWalkAnchor::setup_magic_on_entry(objArrayHandle frames_array) {
    40 void JavaFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
    41   frames_array->obj_at_put(magic_pos, _thread->threadObj());
    41   frames_array->obj_at_put(magic_pos, _thread->threadObj());
    42   _anchor = address_value();
    42   _anchor = address_value();
    43   assert(check_magic(frames_array), "invalid magic");
    43   assert(check_magic(frames_array), "invalid magic");
    44 }
    44 }
    45 
    45 
    46 bool StackWalkAnchor::check_magic(objArrayHandle frames_array) {
    46 bool JavaFrameStream::check_magic(objArrayHandle frames_array) {
    47   oop   m1 = frames_array->obj_at(magic_pos);
    47   oop   m1 = frames_array->obj_at(magic_pos);
    48   jlong m2 = _anchor;
    48   jlong m2 = _anchor;
    49   if (m1 == _thread->threadObj() && m2 == address_value())  return true;
    49   if (m1 == _thread->threadObj() && m2 == address_value())  return true;
    50   return false;
    50   return false;
    51 }
    51 }
    52 
    52 
    53 bool StackWalkAnchor::cleanup_magic_on_exit(objArrayHandle frames_array) {
    53 bool JavaFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) {
    54   bool ok = check_magic(frames_array);
    54   bool ok = check_magic(frames_array);
    55   frames_array->obj_at_put(magic_pos, NULL);
    55   frames_array->obj_at_put(magic_pos, NULL);
    56   _anchor = 0L;
    56   _anchor = 0L;
    57   return ok;
    57   return ok;
    58 }
    58 }
    59 
    59 
    60 // Returns StackWalkAnchor for the current stack being traversed.
    60 // Returns JavaFrameStream for the current stack being traversed.
    61 //
    61 //
    62 // Parameters:
    62 // Parameters:
    63 //  thread         Current Java thread.
    63 //  thread         Current Java thread.
    64 //  magic          Magic value used for each stack walking
    64 //  magic          Magic value used for each stack walking
    65 //  frames_array   User-supplied buffers.  The 0th element is reserved
    65 //  frames_array   User-supplied buffers.  The 0th element is reserved
    66 //                 to this StackWalkAnchor to use
    66 //                 to this JavaFrameStream to use
    67 //
    67 //
    68 StackWalkAnchor* StackWalkAnchor::from_current(JavaThread* thread, jlong magic,
    68 JavaFrameStream* JavaFrameStream::from_current(JavaThread* thread, jlong magic,
    69                                                objArrayHandle frames_array)
    69                                                objArrayHandle frames_array)
    70 {
    70 {
    71   assert(thread != NULL && thread->is_Java_thread(), "");
    71   assert(thread != NULL && thread->is_Java_thread(), "");
    72   oop m1 = frames_array->obj_at(magic_pos);
    72   oop m1 = frames_array->obj_at(magic_pos);
    73   if (m1 != thread->threadObj())      return NULL;
    73   if (m1 != thread->threadObj())      return NULL;
    74   if (magic == 0L)                    return NULL;
    74   if (magic == 0L)                    return NULL;
    75   StackWalkAnchor* anchor = (StackWalkAnchor*) (intptr_t) magic;
    75   JavaFrameStream* stream = (JavaFrameStream*) (intptr_t) magic;
    76   if (!anchor->is_valid_in(thread, frames_array))   return NULL;
    76   if (!stream->is_valid_in(thread, frames_array))   return NULL;
    77   return anchor;
    77   return stream;
    78 }
    78 }
    79 
    79 
    80 // Unpacks one or more frames into user-supplied buffers.
    80 // Unpacks one or more frames into user-supplied buffers.
    81 // Updates the end index, and returns the number of unpacked frames.
    81 // Updates the end index, and returns the number of unpacked frames.
    82 // Always start with the existing vfst.method and bci.
    82 // Always start with the existing vfst.method and bci.
    83 // Do not call vfst.next to advance over the last returned value.
    83 // Do not call vfst.next to advance over the last returned value.
    84 // In other words, do not leave any stale data in the vfst.
    84 // In other words, do not leave any stale data in the vfst.
    85 //
    85 //
    86 // Parameters:
    86 // Parameters:
    87 //   mode           Restrict which frames to be decoded.
    87 //   mode             Restrict which frames to be decoded.
    88 //   vfst           vFrameStream.
    88 //   JavaFrameStream  stream of javaVFrames
    89 //   max_nframes    Maximum number of frames to be filled.
    89 //   max_nframes      Maximum number of frames to be filled.
    90 //   start_index    Start index to the user-supplied buffers.
    90 //   start_index      Start index to the user-supplied buffers.
    91 //   frames_array   Buffer to store Class or StackFrame in, starting at start_index.
    91 //   frames_array     Buffer to store Class or StackFrame in, starting at start_index.
    92 //                  frames array is a Class<?>[] array when only getting caller
    92 //                    frames array is a Class<?>[] array when only getting caller
    93 //                  reference, and a StackFrameInfo[] array (or derivative)
    93 //                    reference, and a StackFrameInfo[] array (or derivative)
    94 //                  otherwise. It should never be null.
    94 //                    otherwise. It should never be null.
    95 //   end_index      End index to the user-supplied buffers with unpacked frames.
    95 //   end_index        End index to the user-supplied buffers with unpacked frames.
    96 //
    96 //
    97 // Returns the number of frames whose information was transferred into the buffers.
    97 // Returns the number of frames whose information was transferred into the buffers.
    98 //
    98 //
    99 int StackWalk::fill_in_frames(jlong mode, vframeStream& vfst,
    99 int StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream,
   100                               int max_nframes, int start_index,
   100                               int max_nframes, int start_index,
   101                               objArrayHandle  frames_array,
   101                               objArrayHandle  frames_array,
   102                               int& end_index, TRAPS) {
   102                               int& end_index, TRAPS) {
   103   if (TraceStackWalk) {
   103   if (TraceStackWalk) {
   104     tty->print_cr("fill_in_frames limit=%d start=%d frames length=%d",
   104     tty->print_cr("fill_in_frames limit=%d start=%d frames length=%d",
   106   }
   106   }
   107   assert(max_nframes > 0, "invalid max_nframes");
   107   assert(max_nframes > 0, "invalid max_nframes");
   108   assert(start_index + max_nframes <= frames_array->length(), "oob");
   108   assert(start_index + max_nframes <= frames_array->length(), "oob");
   109 
   109 
   110   int frames_decoded = 0;
   110   int frames_decoded = 0;
   111   for (; !vfst.at_end(); vfst.next()) {
   111   for (; !stream.at_end(); stream.next()) {
   112     Method* method = vfst.method();
   112     Method* method = stream.method();
   113     int bci = vfst.bci();
   113     int bci = stream.bci();
   114 
   114 
   115     if (method == NULL) continue;
   115     if (method == NULL) continue;
   116     if (!ShowHiddenFrames && StackWalk::skip_hidden_frames(mode)) {
   116     if (!ShowHiddenFrames && StackWalk::skip_hidden_frames(mode)) {
   117       if (method->is_hidden()) {
   117       if (method->is_hidden()) {
   118         if (TraceStackWalk) {
   118         if (TraceStackWalk) {
   131 
   131 
   132     // fill in StackFrameInfo and initialize MemberName
   132     // fill in StackFrameInfo and initialize MemberName
   133     if (live_frame_info(mode)) {
   133     if (live_frame_info(mode)) {
   134       assert (use_frames_array(mode), "Bad mode for get live frame");
   134       assert (use_frames_array(mode), "Bad mode for get live frame");
   135       Handle stackFrame(frames_array->obj_at(index));
   135       Handle stackFrame(frames_array->obj_at(index));
   136       fill_live_stackframe(stackFrame, method, bci, vfst.java_frame(), CHECK_0);
   136       fill_live_stackframe(stackFrame, method, bci, stream.java_frame(), CHECK_0);
   137     } else if (need_method_info(mode)) {
   137     } else if (need_method_info(mode)) {
   138       assert (use_frames_array(mode), "Bad mode for get stack frame");
   138       assert (use_frames_array(mode), "Bad mode for get stack frame");
   139       Handle stackFrame(frames_array->obj_at(index));
   139       Handle stackFrame(frames_array->obj_at(index));
   140       fill_stackframe(stackFrame, method, bci);
   140       fill_stackframe(stackFrame, method, bci);
   141     } else {
   141     } else {
   292 //
   292 //
   293 oop StackWalk::walk(Handle stackStream, jlong mode,
   293 oop StackWalk::walk(Handle stackStream, jlong mode,
   294                     int skip_frames, int frame_count, int start_index,
   294                     int skip_frames, int frame_count, int start_index,
   295                     objArrayHandle frames_array,
   295                     objArrayHandle frames_array,
   296                     TRAPS) {
   296                     TRAPS) {
       
   297   ResourceMark rm(THREAD);
   297   JavaThread* jt = (JavaThread*)THREAD;
   298   JavaThread* jt = (JavaThread*)THREAD;
   298   if (TraceStackWalk) {
   299   if (TraceStackWalk) {
   299     tty->print_cr("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d",
   300     tty->print_cr("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d",
   300                   mode, skip_frames, frame_count);
   301                   mode, skip_frames, frame_count);
   301   }
   302   }
   307   Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
   308   Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
   308   Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
   309   Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
   309 
   310 
   310   methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
   311   methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
   311 
   312 
   312   // Open up a traversable stream onto my stack.
   313   // Setup traversal onto my stack.
   313   // This stream will be made available by *reference* to the inner Java call.
   314   RegisterMap regMap(jt, true);
   314   StackWalkAnchor anchor(jt);
   315   JavaFrameStream stream(jt, &regMap);
   315   vframeStream& vfst = anchor.vframe_stream();
       
   316 
       
   317   {
   316   {
   318     while (!vfst.at_end()) {
   317     while (!stream.at_end()) {
   319       InstanceKlass* ik = vfst.method()->method_holder();
   318       InstanceKlass* ik = stream.method()->method_holder();
   320       if (ik != stackWalker_klass &&
   319       if (ik != stackWalker_klass &&
   321             ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
   320             ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
   322         break;
   321         break;
   323       }
   322       }
   324 
   323 
   325       if (TraceStackWalk) {
   324       if (TraceStackWalk) {
   326         tty->print("  skip "); vfst.method()->print_short_name(); tty->print("\n");
   325         tty->print("  skip "); stream.method()->print_short_name(); tty->print("\n");
   327       }
   326       }
   328       vfst.next();
   327       stream.next();
   329     }
   328     }
   330 
   329 
   331     // stack frame has been traversed individually and resume stack walk
   330     // stack frame has been traversed individually and resume stack walk
   332     // from the stack frame at depth == skip_frames.
   331     // from the stack frame at depth == skip_frames.
   333     for (int n=0; n < skip_frames && !vfst.at_end(); vfst.next(), n++) {
   332     for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
   334       if (TraceStackWalk) {
   333       if (TraceStackWalk) {
   335         tty->print("  skip "); vfst.method()->print_short_name();
   334         tty->print("  skip "); stream.method()->print_short_name();
   336         tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT,
   335         tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT,
   337                       p2i(vfst.frame_id()), p2i(vfst.frame_pc()));
   336                       p2i(stream.java_frame()->fr().id()),
       
   337                       p2i(stream.java_frame()->fr().pc()));
   338       }
   338       }
   339     }
   339     }
   340   }
   340   }
   341 
   341 
   342   // The Method* pointer in the vfst has a very short shelf life.  Grab it now.
       
   343   int end_index = start_index;
   342   int end_index = start_index;
   344   int numFrames = 0;
   343   int numFrames = 0;
   345   if (!vfst.at_end()) {
   344   if (!stream.at_end()) {
   346     numFrames = fill_in_frames(mode, vfst, frame_count, start_index,
   345     numFrames = fill_in_frames(mode, stream, frame_count, start_index,
   347                                frames_array, end_index, CHECK_NULL);
   346                                frames_array, end_index, CHECK_NULL);
   348     if (numFrames < 1) {
   347     if (numFrames < 1) {
   349       THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
   348       THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", NULL);
   350     }
   349     }
   351   }
   350   }
   354   // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk
   353   // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk
   355   // which calls the implementation to consume the stack frames.
   354   // which calls the implementation to consume the stack frames.
   356   // When JVM_CallStackWalk returns, it invalidates the stack stream.
   355   // When JVM_CallStackWalk returns, it invalidates the stack stream.
   357   JavaValue result(T_OBJECT);
   356   JavaValue result(T_OBJECT);
   358   JavaCallArguments args(stackStream);
   357   JavaCallArguments args(stackStream);
   359   args.push_long(anchor.address_value());
   358   args.push_long(stream.address_value());
   360   args.push_int(skip_frames);
   359   args.push_int(skip_frames);
   361   args.push_int(frame_count);
   360   args.push_int(frame_count);
   362   args.push_int(start_index);
   361   args.push_int(start_index);
   363   args.push_int(end_index);
   362   args.push_int(end_index);
   364 
   363 
   365   // Link the thread and vframe stream into the callee-visible object
   364   // Link the thread and vframe stream into the callee-visible object
   366   anchor.setup_magic_on_entry(frames_array);
   365   stream.setup_magic_on_entry(frames_array);
   367 
   366 
   368   JavaCalls::call(&result, m_doStackWalk, &args, THREAD);
   367   JavaCalls::call(&result, m_doStackWalk, &args, THREAD);
   369 
   368 
   370   // Do this before anything else happens, to disable any lingering stream objects
   369   // Do this before anything else happens, to disable any lingering stream objects
   371   bool ok = anchor.cleanup_magic_on_exit(frames_array);
   370   bool ok = stream.cleanup_magic_on_exit(frames_array);
   372 
   371 
   373   // Throw pending exception if we must
   372   // Throw pending exception if we must
   374   (void) (CHECK_NULL);
   373   (void) (CHECK_NULL);
   375 
   374 
   376   if (!ok) {
   375   if (!ok) {
   377     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL);
   376     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL);
   378   }
   377   }
   379 
   378 
   380   // Return normally
   379   // Return normally
   381   return (oop)result.get_jobject();
   380   return (oop)result.get_jobject();
   382 
       
   383 }
   381 }
   384 
   382 
   385 // Walk the next batch of stack frames
   383 // Walk the next batch of stack frames
   386 //
   384 //
   387 // Parameters:
   385 // Parameters:
   398                            int frame_count, int start_index,
   396                            int frame_count, int start_index,
   399                            objArrayHandle frames_array,
   397                            objArrayHandle frames_array,
   400                            TRAPS)
   398                            TRAPS)
   401 {
   399 {
   402   JavaThread* jt = (JavaThread*)THREAD;
   400   JavaThread* jt = (JavaThread*)THREAD;
   403   StackWalkAnchor* existing_anchor = StackWalkAnchor::from_current(jt, magic, frames_array);
   401   JavaFrameStream* existing_stream = JavaFrameStream::from_current(jt, magic, frames_array);
   404   if (existing_anchor == NULL) {
   402   if (existing_stream == NULL) {
   405     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
   403     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
   406   }
   404   }
   407 
   405 
   408   if (frames_array.is_null()) {
   406   if (frames_array.is_null()) {
   409     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L);
   407     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L);
   410   }
   408   }
   411 
   409 
   412   if (TraceStackWalk) {
   410   if (TraceStackWalk) {
   413     tty->print_cr("StackWalk::moreFrames frame_count %d existing_anchor " PTR_FORMAT " start %d frames %d",
   411     tty->print_cr("StackWalk::moreFrames frame_count %d existing_stream " PTR_FORMAT " start %d frames %d",
   414                   frame_count, p2i(existing_anchor), start_index, frames_array->length());
   412                   frame_count, p2i(existing_stream), start_index, frames_array->length());
   415   }
   413   }
   416   int end_index = start_index;
   414   int end_index = start_index;
   417   if (frame_count <= 0) {
   415   if (frame_count <= 0) {
   418     return end_index;        // No operation.
   416     return end_index;        // No operation.
   419   }
   417   }
   420 
   418 
   421   int count = frame_count + start_index;
   419   int count = frame_count + start_index;
   422   assert (frames_array->length() >= count, "not enough space in buffers");
   420   assert (frames_array->length() >= count, "not enough space in buffers");
   423 
   421 
   424   StackWalkAnchor& anchor = (*existing_anchor);
   422   JavaFrameStream& stream = (*existing_stream);
   425   vframeStream& vfst = anchor.vframe_stream();
   423   if (!stream.at_end()) {
   426   if (!vfst.at_end()) {
   424     stream.next(); // advance past the last frame decoded in previous batch
   427     vfst.next();  // this was the last frame decoded in the previous batch
   425     if (!stream.at_end()) {
   428     if (!vfst.at_end()) {
   426       int n = fill_in_frames(mode, stream, frame_count, start_index,
   429       int n = fill_in_frames(mode, vfst, frame_count, start_index,
       
   430                              frames_array, end_index, CHECK_0);
   427                              frames_array, end_index, CHECK_0);
   431       if (n < 1) {
   428       if (n < 1) {
   432         THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
   429         THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
   433       }
   430       }
   434       return end_index;
   431       return end_index;