hotspot/src/share/vm/prims/stackwalk.cpp
changeset 41280 74b314ad1e9a
parent 41095 97cca074c2be
child 41307 a89905798992
equal deleted inserted replaced
41279:5a7c83da4a2d 41280:74b314ad1e9a
    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 JavaFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
    40 void BaseFrameStream::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 JavaFrameStream::check_magic(objArrayHandle frames_array) {
    46 bool BaseFrameStream::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 JavaFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) {
    53 bool BaseFrameStream::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 JavaFrameStream for the current stack being traversed.
    60 JavaFrameStream::JavaFrameStream(JavaThread* thread, int mode)
       
    61   : BaseFrameStream(thread), _vfst(thread) {
       
    62   _need_method_info = StackWalk::need_method_info(mode);
       
    63 }
       
    64 
       
    65 // Returns the BaseFrameStream for the current stack being traversed.
    61 //
    66 //
    62 // Parameters:
    67 // Parameters:
    63 //  thread         Current Java thread.
    68 //  thread         Current Java thread.
    64 //  magic          Magic value used for each stack walking
    69 //  magic          Magic value used for each stack walking
    65 //  frames_array   User-supplied buffers.  The 0th element is reserved
    70 //  frames_array   User-supplied buffers.  The 0th element is reserved
    66 //                 to this JavaFrameStream to use
    71 //                 for this BaseFrameStream to use
    67 //
    72 //
    68 JavaFrameStream* JavaFrameStream::from_current(JavaThread* thread, jlong magic,
    73 BaseFrameStream* BaseFrameStream::from_current(JavaThread* thread, jlong magic,
    69                                                objArrayHandle frames_array)
    74                                                objArrayHandle frames_array)
    70 {
    75 {
    71   assert(thread != NULL && thread->is_Java_thread(), "");
    76   assert(thread != NULL && thread->is_Java_thread(), "");
    72   oop m1 = frames_array->obj_at(magic_pos);
    77   oop m1 = frames_array->obj_at(magic_pos);
    73   if (m1 != thread->threadObj())      return NULL;
    78   if (m1 != thread->threadObj())      return NULL;
    74   if (magic == 0L)                    return NULL;
    79   if (magic == 0L)                    return NULL;
    75   JavaFrameStream* stream = (JavaFrameStream*) (intptr_t) magic;
    80   BaseFrameStream* stream = (BaseFrameStream*) (intptr_t) magic;
    76   if (!stream->is_valid_in(thread, frames_array))   return NULL;
    81   if (!stream->is_valid_in(thread, frames_array))   return NULL;
    77   return stream;
    82   return stream;
    78 }
    83 }
    79 
    84 
    80 // Unpacks one or more frames into user-supplied buffers.
    85 // Unpacks one or more frames into user-supplied buffers.
    83 // Do not call vfst.next to advance over the last returned value.
    88 // 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.
    89 // In other words, do not leave any stale data in the vfst.
    85 //
    90 //
    86 // Parameters:
    91 // Parameters:
    87 //   mode             Restrict which frames to be decoded.
    92 //   mode             Restrict which frames to be decoded.
    88 //   JavaFrameStream  stream of javaVFrames
    93 //   BaseFrameStream  stream of frames
    89 //   max_nframes      Maximum number of frames to be filled.
    94 //   max_nframes      Maximum number of frames to be filled.
    90 //   start_index      Start index to the user-supplied buffers.
    95 //   start_index      Start index to the user-supplied buffers.
    91 //   frames_array     Buffer to store Class or StackFrame in, starting at start_index.
    96 //   frames_array     Buffer to store Class or StackFrame in, starting at start_index.
    92 //                    frames array is a Class<?>[] array when only getting caller
    97 //                    frames array is a Class<?>[] array when only getting caller
    93 //                    reference, and a StackFrameInfo[] array (or derivative)
    98 //                    reference, and a StackFrameInfo[] array (or derivative)
    94 //                    otherwise. It should never be null.
    99 //                    otherwise. It should never be null.
    95 //   end_index        End index to the user-supplied buffers with unpacked frames.
   100 //   end_index        End index to the user-supplied buffers with unpacked frames.
    96 //
   101 //
    97 // Returns the number of frames whose information was transferred into the buffers.
   102 // Returns the number of frames whose information was transferred into the buffers.
    98 //
   103 //
    99 int StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream,
   104 int StackWalk::fill_in_frames(jlong mode, BaseFrameStream& stream,
   100                               int max_nframes, int start_index,
   105                               int max_nframes, int start_index,
   101                               objArrayHandle  frames_array,
   106                               objArrayHandle  frames_array,
   102                               int& end_index, TRAPS) {
   107                               int& end_index, TRAPS) {
   103   if (TraceStackWalk) {
   108   if (TraceStackWalk) {
   104     tty->print_cr("fill_in_frames limit=%d start=%d frames length=%d",
   109     tty->print_cr("fill_in_frames limit=%d start=%d frames length=%d",
   108   assert(start_index + max_nframes <= frames_array->length(), "oob");
   113   assert(start_index + max_nframes <= frames_array->length(), "oob");
   109 
   114 
   110   int frames_decoded = 0;
   115   int frames_decoded = 0;
   111   for (; !stream.at_end(); stream.next()) {
   116   for (; !stream.at_end(); stream.next()) {
   112     Method* method = stream.method();
   117     Method* method = stream.method();
   113     int bci = stream.bci();
       
   114 
   118 
   115     if (method == NULL) continue;
   119     if (method == NULL) continue;
   116 
   120 
   117     // skip hidden frames for default StackWalker option (i.e. SHOW_HIDDEN_FRAMES
   121     // skip hidden frames for default StackWalker option (i.e. SHOW_HIDDEN_FRAMES
   118     // not set) and when StackWalker::getCallerClass is called
   122     // not set) and when StackWalker::getCallerClass is called
   127     }
   131     }
   128 
   132 
   129     int index = end_index++;
   133     int index = end_index++;
   130     if (TraceStackWalk) {
   134     if (TraceStackWalk) {
   131       tty->print("  %d: frame method: ", index); method->print_short_name();
   135       tty->print("  %d: frame method: ", index); method->print_short_name();
   132       tty->print_cr(" bci=%d", bci);
   136       tty->print_cr(" bci=%d", stream.bci());
   133     }
   137     }
   134 
   138 
       
   139     if (!need_method_info(mode) && get_caller_class(mode) &&
       
   140           index == start_index && method->caller_sensitive()) {
       
   141       ResourceMark rm(THREAD);
       
   142       THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),
       
   143         err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method",
       
   144                 method->name_and_sig_as_C_string()));
       
   145     }
   135     // fill in StackFrameInfo and initialize MemberName
   146     // fill in StackFrameInfo and initialize MemberName
   136     if (live_frame_info(mode)) {
   147     stream.fill_frame(index, frames_array, method, CHECK_0);
   137       assert (use_frames_array(mode), "Bad mode for get live frame");
       
   138       Handle stackFrame(frames_array->obj_at(index));
       
   139       fill_live_stackframe(stackFrame, method, bci, stream.java_frame(), CHECK_0);
       
   140     } else if (need_method_info(mode)) {
       
   141       assert (use_frames_array(mode), "Bad mode for get stack frame");
       
   142       Handle stackFrame(frames_array->obj_at(index));
       
   143       fill_stackframe(stackFrame, method, bci);
       
   144     } else {
       
   145       assert (use_frames_array(mode) == false, "Bad mode for filling in Class object");
       
   146       if (get_caller_class(mode) && index == start_index && method->caller_sensitive()) {
       
   147         ResourceMark rm(THREAD);
       
   148         THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),
       
   149           err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method",
       
   150                   method->name_and_sig_as_C_string()));
       
   151       }
       
   152 
       
   153       frames_array->obj_at_put(index, method->method_holder()->java_mirror());
       
   154     }
       
   155     if (++frames_decoded >= max_nframes)  break;
   148     if (++frames_decoded >= max_nframes)  break;
   156   }
   149   }
   157   return frames_decoded;
   150   return frames_decoded;
   158 }
   151 }
   159 
   152 
   160 static oop create_primitive_value_instance(StackValueCollection* values, int i, TRAPS) {
   153 // Fill in the LiveStackFrameInfo at the given index in frames_array
       
   154 void LiveFrameStream::fill_frame(int index, objArrayHandle  frames_array,
       
   155                                  const methodHandle& method, TRAPS) {
       
   156   Handle stackFrame(THREAD, frames_array->obj_at(index));
       
   157   fill_live_stackframe(stackFrame, method, CHECK);
       
   158 }
       
   159 
       
   160 // Fill in the StackFrameInfo at the given index in frames_array
       
   161 void JavaFrameStream::fill_frame(int index, objArrayHandle  frames_array,
       
   162                                  const methodHandle& method, TRAPS) {
       
   163   if (_need_method_info) {
       
   164     Handle stackFrame(THREAD, frames_array->obj_at(index));
       
   165     fill_stackframe(stackFrame, method);
       
   166   } else {
       
   167     frames_array->obj_at_put(index, method->method_holder()->java_mirror());
       
   168   }
       
   169 }
       
   170 
       
   171 oop LiveFrameStream::create_primitive_value_instance(StackValueCollection* values, int i, TRAPS) {
   161   Klass* k = SystemDictionary::resolve_or_null(vmSymbols::java_lang_LiveStackFrameInfo(), CHECK_NULL);
   172   Klass* k = SystemDictionary::resolve_or_null(vmSymbols::java_lang_LiveStackFrameInfo(), CHECK_NULL);
   162   instanceKlassHandle ik (THREAD, k);
   173   instanceKlassHandle ik (THREAD, k);
   163 
   174 
   164   JavaValue result(T_OBJECT);
   175   JavaValue result(T_OBJECT);
   165   JavaCallArguments args;
   176   JavaCallArguments args;
   226                          &args,
   237                          &args,
   227                          CHECK_NULL);
   238                          CHECK_NULL);
   228   return (instanceOop) result.get_jobject();
   239   return (instanceOop) result.get_jobject();
   229 }
   240 }
   230 
   241 
   231 static objArrayHandle values_to_object_array(StackValueCollection* values, TRAPS) {
   242 objArrayHandle LiveFrameStream::values_to_object_array(StackValueCollection* values, TRAPS) {
   232   objArrayHandle empty;
   243   objArrayHandle empty;
   233   int length = values->size();
   244   int length = values->size();
   234   objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(),
   245   objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(),
   235                                                    length, CHECK_(empty));
   246                                                    length, CHECK_(empty));
   236   objArrayHandle array_h(THREAD, array_oop);
   247   objArrayHandle array_h(THREAD, array_oop);
   241       array_h->obj_at_put(i, obj);
   252       array_h->obj_at_put(i, obj);
   242   }
   253   }
   243   return array_h;
   254   return array_h;
   244 }
   255 }
   245 
   256 
   246 static objArrayHandle monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors, TRAPS) {
   257 objArrayHandle LiveFrameStream::monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors, TRAPS) {
   247   int length = monitors->length();
   258   int length = monitors->length();
   248   objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(),
   259   objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(),
   249                                                    length, CHECK_(objArrayHandle()));
   260                                                    length, CHECK_(objArrayHandle()));
   250   objArrayHandle array_h(THREAD, array_oop);
   261   objArrayHandle array_h(THREAD, array_oop);
   251   for (int i = 0; i < length; i++) {
   262   for (int i = 0; i < length; i++) {
   254   }
   265   }
   255   return array_h;
   266   return array_h;
   256 }
   267 }
   257 
   268 
   258 // Fill StackFrameInfo with declaringClass and bci and initialize memberName
   269 // Fill StackFrameInfo with declaringClass and bci and initialize memberName
   259 void StackWalk::fill_stackframe(Handle stackFrame, const methodHandle& method, int bci) {
   270 void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method) {
   260   java_lang_StackFrameInfo::set_declaringClass(stackFrame(), method->method_holder()->java_mirror());
   271   java_lang_StackFrameInfo::set_declaringClass(stackFrame(), method->method_holder()->java_mirror());
   261   java_lang_StackFrameInfo::set_method_and_bci(stackFrame(), method, bci);
   272   java_lang_StackFrameInfo::set_method_and_bci(stackFrame(), method, bci());
   262 }
   273 }
   263 
   274 
   264 // Fill LiveStackFrameInfo with locals, monitors, and expressions
   275 // Fill LiveStackFrameInfo with locals, monitors, and expressions
   265 void StackWalk::fill_live_stackframe(Handle stackFrame, const methodHandle& method,
   276 void LiveFrameStream::fill_live_stackframe(Handle stackFrame,
   266                                      int bci, javaVFrame* jvf, TRAPS) {
   277                                            const methodHandle& method, TRAPS) {
   267   fill_stackframe(stackFrame, method, bci);
   278   fill_stackframe(stackFrame, method);
   268   if (jvf != NULL) {
   279   if (_jvf != NULL) {
   269     StackValueCollection* locals = jvf->locals();
   280     StackValueCollection* locals = _jvf->locals();
   270     StackValueCollection* expressions = jvf->expressions();
   281     StackValueCollection* expressions = _jvf->expressions();
   271     GrowableArray<MonitorInfo*>* monitors = jvf->monitors();
   282     GrowableArray<MonitorInfo*>* monitors = _jvf->monitors();
   272 
   283 
   273     if (!locals->is_empty()) {
   284     if (!locals->is_empty()) {
   274       objArrayHandle locals_h = values_to_object_array(locals, CHECK);
   285       objArrayHandle locals_h = values_to_object_array(locals, CHECK);
   275       java_lang_LiveStackFrameInfo::set_locals(stackFrame(), locals_h());
   286       java_lang_LiveStackFrameInfo::set_locals(stackFrame(), locals_h());
   276     }
   287     }
   313 
   324 
   314   if (frames_array.is_null()) {
   325   if (frames_array.is_null()) {
   315     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
   326     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
   316   }
   327   }
   317 
   328 
   318   Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
   329   // Setup traversal onto my stack.
   319   Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
   330   if (live_frame_info(mode)) {
   320 
   331     assert (use_frames_array(mode), "Bad mode for get live frame");
       
   332     RegisterMap regMap(jt, true);
       
   333     LiveFrameStream stream(jt, &regMap);
       
   334     return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count, start_index, frames_array, CHECK_NULL);
       
   335   } else {
       
   336     JavaFrameStream stream(jt, mode);
       
   337     return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count, start_index, frames_array, CHECK_NULL);
       
   338   }
       
   339 }
       
   340 
       
   341 oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
       
   342                                jlong mode, int skip_frames, int frame_count,
       
   343                                int start_index, objArrayHandle frames_array, TRAPS) {
   321   methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
   344   methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
   322 
   345 
   323   // Setup traversal onto my stack.
       
   324   RegisterMap regMap(jt, true);
       
   325   JavaFrameStream stream(jt, &regMap);
       
   326   {
   346   {
       
   347     Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
       
   348     Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
   327     while (!stream.at_end()) {
   349     while (!stream.at_end()) {
   328       InstanceKlass* ik = stream.method()->method_holder();
   350       InstanceKlass* ik = stream.method()->method_holder();
   329       if (ik != stackWalker_klass &&
   351       if (ik != stackWalker_klass &&
   330             ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
   352             ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
   331         break;
   353         break;
   339 
   361 
   340     // stack frame has been traversed individually and resume stack walk
   362     // stack frame has been traversed individually and resume stack walk
   341     // from the stack frame at depth == skip_frames.
   363     // from the stack frame at depth == skip_frames.
   342     for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
   364     for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
   343       if (TraceStackWalk) {
   365       if (TraceStackWalk) {
   344         tty->print("  skip "); stream.method()->print_short_name();
   366         tty->print("  skip "); stream.method()->print_short_name(); tty->cr();
   345         tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT,
       
   346                       p2i(stream.java_frame()->fr().id()),
       
   347                       p2i(stream.java_frame()->fr().pc()));
       
   348       }
   367       }
   349     }
   368     }
   350   }
   369   }
   351 
   370 
   352   int end_index = start_index;
   371   int end_index = start_index;
   400 //   start_index    Start index to the user-supplied buffers.
   419 //   start_index    Start index to the user-supplied buffers.
   401 //   frames_array   Buffer to store StackFrame in, starting at start_index.
   420 //   frames_array   Buffer to store StackFrame in, starting at start_index.
   402 //
   421 //
   403 // Returns the end index of frame filled in the buffer.
   422 // Returns the end index of frame filled in the buffer.
   404 //
   423 //
   405 jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
   424 jint StackWalk::fetchNextBatch(Handle stackStream, jlong mode, jlong magic,
   406                            int frame_count, int start_index,
   425                                int frame_count, int start_index,
   407                            objArrayHandle frames_array,
   426                                objArrayHandle frames_array,
   408                            TRAPS)
   427                                TRAPS)
   409 {
   428 {
   410   JavaThread* jt = (JavaThread*)THREAD;
   429   JavaThread* jt = (JavaThread*)THREAD;
   411   JavaFrameStream* existing_stream = JavaFrameStream::from_current(jt, magic, frames_array);
   430   BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array);
   412   if (existing_stream == NULL) {
   431   if (existing_stream == NULL) {
   413     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
   432     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
   414   }
   433   }
   415 
   434 
   416   if (frames_array.is_null()) {
   435   if (frames_array.is_null()) {
   417     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L);
   436     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L);
   418   }
   437   }
   419 
   438 
   420   if (TraceStackWalk) {
   439   if (TraceStackWalk) {
   421     tty->print_cr("StackWalk::moreFrames frame_count %d existing_stream " PTR_FORMAT " start %d frames %d",
   440     tty->print_cr("StackWalk::fetchNextBatch frame_count %d existing_stream " PTR_FORMAT " start %d frames %d",
   422                   frame_count, p2i(existing_stream), start_index, frames_array->length());
   441                   frame_count, p2i(existing_stream), start_index, frames_array->length());
   423   }
   442   }
   424   int end_index = start_index;
   443   int end_index = start_index;
   425   if (frame_count <= 0) {
   444   if (frame_count <= 0) {
   426     return end_index;        // No operation.
   445     return end_index;        // No operation.
   427   }
   446   }
   428 
   447 
   429   int count = frame_count + start_index;
   448   int count = frame_count + start_index;
   430   assert (frames_array->length() >= count, "not enough space in buffers");
   449   assert (frames_array->length() >= count, "not enough space in buffers");
   431 
   450 
   432   JavaFrameStream& stream = (*existing_stream);
   451   BaseFrameStream& stream = (*existing_stream);
   433   if (!stream.at_end()) {
   452   if (!stream.at_end()) {
   434     stream.next(); // advance past the last frame decoded in previous batch
   453     stream.next(); // advance past the last frame decoded in previous batch
   435     if (!stream.at_end()) {
   454     if (!stream.at_end()) {
   436       int n = fill_in_frames(mode, stream, frame_count, start_index,
   455       int n = fill_in_frames(mode, stream, frame_count, start_index,
   437                              frames_array, end_index, CHECK_0);
   456                              frames_array, end_index, CHECK_0);