< prev index next >

src/hotspot/share/prims/stackwalk.cpp

Print this page




  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/javaClasses.hpp"
  27 #include "classfile/javaClasses.inline.hpp"
  28 #include "classfile/vmSymbols.hpp"
  29 #include "logging/log.hpp"
  30 #include "logging/logStream.hpp"
  31 #include "memory/oopFactory.hpp"
  32 #include "memory/universe.hpp"
  33 #include "oops/oop.inline.hpp"
  34 #include "oops/objArrayOop.inline.hpp"
  35 #include "prims/stackwalk.hpp"
  36 #include "runtime/globals.hpp"
  37 #include "runtime/handles.inline.hpp"
  38 #include "runtime/javaCalls.hpp"
  39 #include "runtime/thread.inline.hpp"
  40 #include "runtime/vframe.inline.hpp"
  41 #include "utilities/globalDefinitions.hpp"
  42 
  43 // setup and cleanup actions





  44 void BaseFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
  45   frames_array->obj_at_put(magic_pos, _thread->threadObj());
  46   _anchor = address_value();
  47   assert(check_magic(frames_array), "invalid magic");
  48 }
  49 
  50 bool BaseFrameStream::check_magic(objArrayHandle frames_array) {
  51   oop   m1 = frames_array->obj_at(magic_pos);
  52   jlong m2 = _anchor;
  53   if (oopDesc::equals(m1, _thread->threadObj()) && m2 == address_value())  return true;
  54   return false;
  55 }
  56 
  57 bool BaseFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) {
  58   bool ok = check_magic(frames_array);
  59   frames_array->obj_at_put(magic_pos, NULL);
  60   _anchor = 0L;
  61   return ok;
  62 }
  63 
  64 JavaFrameStream::JavaFrameStream(JavaThread* thread, int mode)
  65   : BaseFrameStream(thread), _vfst(thread) {

























  66   _need_method_info = StackWalk::need_method_info(mode);
  67 }
  68 
  69 void JavaFrameStream::next() { _vfst.next();}

















































  70 
  71 // Returns the BaseFrameStream for the current stack being traversed.
  72 //
  73 // Parameters:
  74 //  thread         Current Java thread.
  75 //  magic          Magic value used for each stack walking
  76 //  frames_array   User-supplied buffers.  The 0th element is reserved
  77 //                 for this BaseFrameStream to use
  78 //
  79 BaseFrameStream* BaseFrameStream::from_current(JavaThread* thread, jlong magic,
  80                                                objArrayHandle frames_array)
  81 {
  82   assert(thread != NULL && thread->is_Java_thread(), "");
  83   oop m1 = frames_array->obj_at(magic_pos);
  84   if (!oopDesc::equals(m1, thread->threadObj())) return NULL;
  85   if (magic == 0L)                    return NULL;
  86   BaseFrameStream* stream = (BaseFrameStream*) (intptr_t) magic;
  87   if (!stream->is_valid_in(thread, frames_array))   return NULL;
  88   return stream;
  89 }


 140 
 141     int index = end_index++;
 142     LogTarget(Debug, stackwalk) lt;
 143     if (lt.is_enabled()) {
 144       ResourceMark rm(THREAD);
 145       LogStream ls(lt);
 146       ls.print("  %d: frame method: ", index);
 147       method->print_short_name(&ls);
 148       ls.print_cr(" bci=%d", stream.bci());
 149     }
 150 
 151     if (!need_method_info(mode) && get_caller_class(mode) &&
 152           index == start_index && method->caller_sensitive()) {
 153       ResourceMark rm(THREAD);
 154       THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),
 155         err_msg("StackWalker::getCallerClass called from @CallerSensitive '%s' method",
 156                 method->external_name()));
 157     }
 158     // fill in StackFrameInfo and initialize MemberName
 159     stream.fill_frame(index, frames_array, method, CHECK_0);








 160     if (++frames_decoded >= max_nframes)  break;
 161   }


 162   return frames_decoded;
 163 }
 164 
 165 // Fill in the LiveStackFrameInfo at the given index in frames_array
 166 void LiveFrameStream::fill_frame(int index, objArrayHandle  frames_array,
 167                                  const methodHandle& method, TRAPS) {
 168   HandleMark hm(THREAD);
 169   Handle stackFrame(THREAD, frames_array->obj_at(index));
 170   fill_live_stackframe(stackFrame, method, CHECK);
 171 }
 172 
 173 // Fill in the StackFrameInfo at the given index in frames_array
 174 void JavaFrameStream::fill_frame(int index, objArrayHandle  frames_array,
 175                                  const methodHandle& method, TRAPS) {
 176   if (_need_method_info) {
 177     HandleMark hm(THREAD);
 178     Handle stackFrame(THREAD, frames_array->obj_at(index));
 179     fill_stackframe(stackFrame, method, CHECK);
 180   } else {
 181     frames_array->obj_at_put(index, method->method_holder()->java_mirror());


 263       array_h->obj_at_put(i, obj);
 264     }
 265   }
 266   return array_h;
 267 }
 268 
 269 objArrayHandle LiveFrameStream::monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors, TRAPS) {
 270   int length = monitors->length();
 271   objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(),
 272                                                    length, CHECK_(objArrayHandle()));
 273   objArrayHandle array_h(THREAD, array_oop);
 274   for (int i = 0; i < length; i++) {
 275     MonitorInfo* monitor = monitors->at(i);
 276     array_h->obj_at_put(i, monitor->owner());
 277   }
 278   return array_h;
 279 }
 280 
 281 // Fill StackFrameInfo with bci and initialize memberName
 282 void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method, TRAPS) {
 283   java_lang_StackFrameInfo::set_method_and_bci(stackFrame, method, bci(), THREAD);
 284 }
 285 
 286 // Fill LiveStackFrameInfo with locals, monitors, and expressions
 287 void LiveFrameStream::fill_live_stackframe(Handle stackFrame,
 288                                            const methodHandle& method, TRAPS) {
 289   fill_stackframe(stackFrame, method, CHECK);
 290   if (_jvf != NULL) {
 291     StackValueCollection* locals = _jvf->locals();
 292     StackValueCollection* expressions = _jvf->expressions();
 293     GrowableArray<MonitorInfo*>* monitors = _jvf->monitors();
 294 
 295     int mode = 0;
 296     if (_jvf->is_interpreted_frame()) {
 297       mode = MODE_INTERPRETED;
 298     } else if (_jvf->is_compiled_frame()) {
 299       mode = MODE_COMPILED;
 300     }
 301 
 302     if (!locals->is_empty()) {
 303       objArrayHandle locals_h = values_to_object_array(locals, CHECK);
 304       java_lang_LiveStackFrameInfo::set_locals(stackFrame(), locals_h());
 305     }
 306     if (!expressions->is_empty()) {
 307       objArrayHandle expressions_h = values_to_object_array(expressions, CHECK);
 308       java_lang_LiveStackFrameInfo::set_operands(stackFrame(), expressions_h());
 309     }
 310     if (monitors->length() > 0) {
 311       objArrayHandle monitors_h = monitors_to_object_array(monitors, CHECK);
 312       java_lang_LiveStackFrameInfo::set_monitors(stackFrame(), monitors_h());
 313     }
 314     java_lang_LiveStackFrameInfo::set_mode(stackFrame(), mode);
 315   }
 316 }
 317 
 318 // Begins stack walking.
 319 //
 320 // Parameters:
 321 //   stackStream    StackStream object
 322 //   mode           Stack walking mode.
 323 //   skip_frames    Number of frames to be skipped.

 324 //   frame_count    Number of frames to be traversed.
 325 //   start_index    Start index to the user-supplied buffers.
 326 //   frames_array   Buffer to store StackFrame in, starting at start_index.
 327 //                  frames array is a Class<?>[] array when only getting caller
 328 //                  reference, and a StackFrameInfo[] array (or derivative)
 329 //                  otherwise. It should never be null.
 330 //
 331 // Returns Object returned from AbstractStackWalker::doStackWalk call.
 332 //
 333 oop StackWalk::walk(Handle stackStream, jlong mode,
 334                     int skip_frames, int frame_count, int start_index,
 335                     objArrayHandle frames_array,
 336                     TRAPS) {
 337   ResourceMark rm(THREAD);


 338   JavaThread* jt = (JavaThread*)THREAD;
 339   log_debug(stackwalk)("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d",
 340                        mode, skip_frames, frame_count);







 341 
 342   if (frames_array.is_null()) {
 343     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
 344   }
 345 
 346   // Setup traversal onto my stack.
 347   if (live_frame_info(mode)) {
 348     assert (use_frames_array(mode), "Bad mode for get live frame");
 349     RegisterMap regMap(jt, true);
 350     LiveFrameStream stream(jt, &regMap);
 351     return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
 352                            start_index, frames_array, THREAD);
 353   } else {
 354     JavaFrameStream stream(jt, mode);
 355     return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
 356                            start_index, frames_array, THREAD);
 357   }
 358 }
 359 
 360 oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
 361                                jlong mode, int skip_frames, int frame_count,
 362                                int start_index, objArrayHandle frames_array, TRAPS) {
 363   methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
 364 
 365   {
 366     Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
 367     Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
 368     while (!stream.at_end()) {
 369       InstanceKlass* ik = stream.method()->method_holder();
 370       if (ik != stackWalker_klass &&
 371             ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
 372         break;
 373       }
 374 


 434     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL);
 435   }
 436 
 437   // Return normally
 438   return (oop)result.get_jobject();
 439 }
 440 
 441 // Walk the next batch of stack frames
 442 //
 443 // Parameters:
 444 //   stackStream    StackStream object
 445 //   mode           Stack walking mode.
 446 //   magic          Must be valid value to continue the stack walk
 447 //   frame_count    Number of frames to be decoded.
 448 //   start_index    Start index to the user-supplied buffers.
 449 //   frames_array   Buffer to store StackFrame in, starting at start_index.
 450 //
 451 // Returns the end index of frame filled in the buffer.
 452 //
 453 jint StackWalk::fetchNextBatch(Handle stackStream, jlong mode, jlong magic,
 454                                int frame_count, int start_index,
 455                                objArrayHandle frames_array,
 456                                TRAPS)
 457 {
 458   JavaThread* jt = (JavaThread*)THREAD;
 459   BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array);
 460   if (existing_stream == NULL) {
 461     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
 462   }
 463 
 464   if (frames_array.is_null()) {
 465     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L);
 466   }
 467 
 468   log_debug(stackwalk)("StackWalk::fetchNextBatch frame_count %d existing_stream "
 469                        PTR_FORMAT " start %d frames %d",
 470                        frame_count, p2i(existing_stream), start_index, frames_array->length());
 471   int end_index = start_index;
 472   if (frame_count <= 0) {
 473     return end_index;        // No operation.
 474   }
 475 
 476   int count = frame_count + start_index;
 477   assert (frames_array->length() >= count, "not enough space in buffers");
 478 
 479   BaseFrameStream& stream = (*existing_stream);
 480   if (!stream.at_end()) {
 481     stream.next(); // advance past the last frame decoded in previous batch
 482     if (!stream.at_end()) {
 483       int n = fill_in_frames(mode, stream, frame_count, start_index,
 484                              frames_array, end_index, CHECK_0);
 485       if (n < 1) {
 486         THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
 487       }
 488       return end_index;
 489     }
 490   }
 491   return end_index;















 492 }


  24 
  25 #include "precompiled.hpp"
  26 #include "classfile/javaClasses.hpp"
  27 #include "classfile/javaClasses.inline.hpp"
  28 #include "classfile/vmSymbols.hpp"
  29 #include "logging/log.hpp"
  30 #include "logging/logStream.hpp"
  31 #include "memory/oopFactory.hpp"
  32 #include "memory/universe.hpp"
  33 #include "oops/oop.inline.hpp"
  34 #include "oops/objArrayOop.inline.hpp"
  35 #include "prims/stackwalk.hpp"
  36 #include "runtime/globals.hpp"
  37 #include "runtime/handles.inline.hpp"
  38 #include "runtime/javaCalls.hpp"
  39 #include "runtime/thread.inline.hpp"
  40 #include "runtime/vframe.inline.hpp"
  41 #include "utilities/globalDefinitions.hpp"
  42 
  43 // setup and cleanup actions
  44 BaseFrameStream::BaseFrameStream(JavaThread* thread, Handle continuation) 
  45   : _thread(thread), _continuation(continuation), _anchor(0L) {
  46     assert (thread != NULL, "");
  47 }
  48 
  49 void BaseFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
  50   frames_array->obj_at_put(magic_pos, _thread->threadObj());
  51   _anchor = address_value();
  52   assert(check_magic(frames_array), "invalid magic");
  53 }
  54 
  55 bool BaseFrameStream::check_magic(objArrayHandle frames_array) {
  56   oop   m1 = frames_array->obj_at(magic_pos);
  57   jlong m2 = _anchor;
  58   if (oopDesc::equals(m1, _thread->threadObj()) && m2 == address_value())  return true;
  59   return false;
  60 }
  61 
  62 bool BaseFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) {
  63   bool ok = check_magic(frames_array);
  64   frames_array->obj_at_put(magic_pos, NULL);
  65   _anchor = 0L;
  66   return ok;
  67 }
  68 
  69 void BaseFrameStream::set_continuation(Handle cont) {
  70   // ensure that the lifetime of the handle is that of the entire walk
  71   // This actually also sets a copy of the handle in the RegisterMap,
  72   // but that's OK, because we want them to be the same, anyway.
  73   // (although we don't rely on this sharing, and set the other copy again)
  74   // tty->print_cr("-- BaseFrameStream::set_continuation: %p", (oopDesc*)cont());
  75   *(_continuation.raw_value()) = cont();
  76 }
  77 
  78 // static inline Handle continuation_of(Handle cont_or_scope) {
  79 //   return (cont_or_scope.not_null() && cont_or_scope()->is_a(SystemDictionary::Continuation_klass()))
  80 //             ? cont_or_scope
  81 //             : Handle();
  82 // }
  83 
  84 // static inline Handle continuationScope_of(JavaThread* thread, Handle cont_or_scope) {
  85 //   if (cont_or_scope.is_null() || cont_or_scope()->is_a(SystemDictionary::ContinuationScope_klass()))
  86 //     return cont_or_scope;
  87 //   assert (cont_or_scope()->is_a(SystemDictionary::Continuation_klass()), "must be");
  88 //   return Handle(thread, Continuation::continuation_scope(cont_or_scope()));
  89 // }
  90 
  91 JavaFrameStream::JavaFrameStream(JavaThread* thread, int mode, Handle cont_scope, Handle cont)
  92   : BaseFrameStream(thread, cont), 
  93    _vfst(cont.is_null()
  94       ? vframeStream(thread, cont_scope)
  95       : vframeStream(cont)) {
  96   _need_method_info = StackWalk::need_method_info(mode);
  97 }
  98 
  99 LiveFrameStream::LiveFrameStream(JavaThread* thread, RegisterMap* rm, Handle cont_scope, Handle cont)
 100    : BaseFrameStream(thread, cont), _cont_scope(cont_scope),
 101     _cont(cont.not_null() ? cont : Handle(thread, thread->last_continuation())) {
 102      
 103     _map = rm;
 104     if (cont.is_null()) {
 105       _jvf  = thread->last_java_vframe(rm);
 106       // _cont = Handle(thread, thread->last_continuation());
 107     } else {
 108       _jvf  = Continuation::has_last_Java_frame(cont) ? Continuation::last_java_vframe(cont, rm) : NULL;
 109       // _cont = cont;
 110     }
 111 }
 112 
 113 void JavaFrameStream::set_continuation(Handle cont) {
 114   BaseFrameStream::set_continuation(cont);
 115 
 116   _vfst = vframeStream(continuation()); // we must not use the handle argument (lifetime; see BaseFrameStream::set_continuation)
 117 }
 118 
 119 void LiveFrameStream::set_continuation(Handle cont) {
 120   BaseFrameStream::set_continuation(cont);
 121 
 122   _jvf = Continuation::last_java_vframe(continuation(), _map); // we must not use the handle argument (lifetime; see BaseFrameStream::set_continuation)
 123   _cont = continuation(); // *(_cont.raw_value()) = cont(); // preserve handle
 124   tty->print_cr("-- LiveFrameStream::set_continuation: %p", (oopDesc*)_cont());
 125 }
 126 
 127 void JavaFrameStream::next() { 
 128   _vfst.next(); 
 129 }
 130 
 131 void LiveFrameStream::next() {
 132   assert (_cont_scope.is_null() || _cont.not_null(), "must be");
 133   if (_cont.not_null() && Continuation::is_continuation_entry_frame(_jvf->fr(), _jvf->register_map())) {
 134     oop cont = _cont();
 135     oop scope = java_lang_Continuation::scope(cont);
 136 
 137     *(_cont.raw_value()) = java_lang_Continuation::parent(cont);
 138     
 139     if (_cont_scope.not_null() && oopDesc::equals(scope, _cont_scope())) {
 140       assert (Continuation::is_frame_in_continuation(_jvf->fr(), cont), "must be");
 141       _jvf = NULL;
 142       return;
 143     }
 144   }
 145   assert (!Continuation::is_scope_bottom(_cont_scope(), _jvf->fr(), _jvf->register_map()), "");
 146   
 147   _jvf = _jvf->java_sender();
 148 }
 149 
 150 // Returns the BaseFrameStream for the current stack being traversed.
 151 //
 152 // Parameters:
 153 //  thread         Current Java thread.
 154 //  magic          Magic value used for each stack walking
 155 //  frames_array   User-supplied buffers.  The 0th element is reserved
 156 //                 for this BaseFrameStream to use
 157 //
 158 BaseFrameStream* BaseFrameStream::from_current(JavaThread* thread, jlong magic,
 159                                                objArrayHandle frames_array)
 160 {
 161   assert(thread != NULL && thread->is_Java_thread(), "");
 162   oop m1 = frames_array->obj_at(magic_pos);
 163   if (!oopDesc::equals(m1, thread->threadObj())) return NULL;
 164   if (magic == 0L)                    return NULL;
 165   BaseFrameStream* stream = (BaseFrameStream*) (intptr_t) magic;
 166   if (!stream->is_valid_in(thread, frames_array))   return NULL;
 167   return stream;
 168 }


 219 
 220     int index = end_index++;
 221     LogTarget(Debug, stackwalk) lt;
 222     if (lt.is_enabled()) {
 223       ResourceMark rm(THREAD);
 224       LogStream ls(lt);
 225       ls.print("  %d: frame method: ", index);
 226       method->print_short_name(&ls);
 227       ls.print_cr(" bci=%d", stream.bci());
 228     }
 229 
 230     if (!need_method_info(mode) && get_caller_class(mode) &&
 231           index == start_index && method->caller_sensitive()) {
 232       ResourceMark rm(THREAD);
 233       THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),
 234         err_msg("StackWalker::getCallerClass called from @CallerSensitive '%s' method",
 235                 method->external_name()));
 236     }
 237     // fill in StackFrameInfo and initialize MemberName
 238     stream.fill_frame(index, frames_array, method, CHECK_0);
 239 
 240     if (lt.is_enabled()) {
 241       ResourceMark rm(THREAD);
 242       LogStream ls(lt);
 243       ls.print("  %d: done frame method: ", index);
 244       method->print_short_name(&ls);
 245     }
 246 
 247     if (++frames_decoded >= max_nframes)  break;
 248   }
 249   log_debug(stackwalk)("fill_in_frames done frames_decoded=%d at_end=%d", frames_decoded, stream.at_end());
 250 
 251   return frames_decoded;
 252 }
 253 
 254 // Fill in the LiveStackFrameInfo at the given index in frames_array
 255 void LiveFrameStream::fill_frame(int index, objArrayHandle  frames_array,
 256                                  const methodHandle& method, TRAPS) {
 257   HandleMark hm(THREAD);
 258   Handle stackFrame(THREAD, frames_array->obj_at(index));
 259   fill_live_stackframe(stackFrame, method, CHECK);
 260 }
 261 
 262 // Fill in the StackFrameInfo at the given index in frames_array
 263 void JavaFrameStream::fill_frame(int index, objArrayHandle  frames_array,
 264                                  const methodHandle& method, TRAPS) {
 265   if (_need_method_info) {
 266     HandleMark hm(THREAD);
 267     Handle stackFrame(THREAD, frames_array->obj_at(index));
 268     fill_stackframe(stackFrame, method, CHECK);
 269   } else {
 270     frames_array->obj_at_put(index, method->method_holder()->java_mirror());


 352       array_h->obj_at_put(i, obj);
 353     }
 354   }
 355   return array_h;
 356 }
 357 
 358 objArrayHandle LiveFrameStream::monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors, TRAPS) {
 359   int length = monitors->length();
 360   objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(),
 361                                                    length, CHECK_(objArrayHandle()));
 362   objArrayHandle array_h(THREAD, array_oop);
 363   for (int i = 0; i < length; i++) {
 364     MonitorInfo* monitor = monitors->at(i);
 365     array_h->obj_at_put(i, monitor->owner());
 366   }
 367   return array_h;
 368 }
 369 
 370 // Fill StackFrameInfo with bci and initialize memberName
 371 void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method, TRAPS) {
 372   java_lang_StackFrameInfo::set_method_and_bci(stackFrame, method, bci(), cont(), THREAD);
 373 }
 374 
 375 // Fill LiveStackFrameInfo with locals, monitors, and expressions
 376 void LiveFrameStream::fill_live_stackframe(Handle stackFrame,
 377                                            const methodHandle& method, TRAPS) {
 378   fill_stackframe(stackFrame, method, CHECK);
 379   if (_jvf != NULL) {
 380     StackValueCollection* locals = _jvf->locals();
 381     StackValueCollection* expressions = _jvf->expressions();
 382     GrowableArray<MonitorInfo*>* monitors = _jvf->monitors();
 383 
 384     int mode = 0;
 385     if (_jvf->is_interpreted_frame()) {
 386       mode = MODE_INTERPRETED;
 387     } else if (_jvf->is_compiled_frame()) {
 388       mode = MODE_COMPILED;
 389     }
 390 
 391     if (!locals->is_empty()) {
 392       objArrayHandle locals_h = values_to_object_array(locals, CHECK);
 393       java_lang_LiveStackFrameInfo::set_locals(stackFrame(), locals_h());
 394     }
 395     if (!expressions->is_empty()) {
 396       objArrayHandle expressions_h = values_to_object_array(expressions, CHECK);
 397       java_lang_LiveStackFrameInfo::set_operands(stackFrame(), expressions_h());
 398     }
 399     if (monitors->length() > 0) {
 400       objArrayHandle monitors_h = monitors_to_object_array(monitors, CHECK);
 401       java_lang_LiveStackFrameInfo::set_monitors(stackFrame(), monitors_h());
 402     }
 403     java_lang_LiveStackFrameInfo::set_mode(stackFrame(), mode);
 404   }
 405 }
 406 
 407 // Begins stack walking.
 408 //
 409 // Parameters:
 410 //   stackStream    StackStream object
 411 //   mode           Stack walking mode.
 412 //   skip_frames    Number of frames to be skipped.
 413 //   cont_scope     Continuation scope to walk (if not in this scope, we'll walk all the way).
 414 //   frame_count    Number of frames to be traversed.
 415 //   start_index    Start index to the user-supplied buffers.
 416 //   frames_array   Buffer to store StackFrame in, starting at start_index.
 417 //                  frames array is a Class<?>[] array when only getting caller
 418 //                  reference, and a StackFrameInfo[] array (or derivative)
 419 //                  otherwise. It should never be null.
 420 //
 421 // Returns Object returned from AbstractStackWalker::doStackWalk call.
 422 //
 423 oop StackWalk::walk(Handle stackStream, jlong mode, int skip_frames, Handle cont_scope, Handle cont, 
 424                     int frame_count, int start_index, objArrayHandle frames_array,

 425                     TRAPS) {
 426   ResourceMark rm(THREAD);
 427   HandleMark hm(THREAD); // needed to store a continuation in the RegisterMap
 428 
 429   JavaThread* jt = (JavaThread*)THREAD;
 430   log_debug(stackwalk)("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d", mode, skip_frames, frame_count);
 431   LogTarget(Debug, stackwalk) lt;
 432   if (lt.is_enabled()) {
 433     ResourceMark rm(THREAD);
 434     LogStream ls(lt);
 435     ls.print("cont_scope: ");
 436     cont_scope()->print_on(&ls);
 437     ls.cr();
 438   }
 439 
 440   if (frames_array.is_null()) {
 441     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
 442   }
 443 
 444   // Setup traversal onto my stack.
 445   if (live_frame_info(mode)) {
 446     assert (use_frames_array(mode), "Bad mode for get live frame");
 447     RegisterMap regMap(jt, true, true);
 448     LiveFrameStream stream(jt, &regMap, cont_scope, cont);
 449     return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
 450                            start_index, frames_array, THREAD);
 451   } else {
 452     JavaFrameStream stream(jt, mode, cont_scope, cont);
 453     return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
 454                            start_index, frames_array, THREAD);
 455   }
 456 }
 457 
 458 oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
 459                                jlong mode, int skip_frames, int frame_count,
 460                                int start_index, objArrayHandle frames_array, TRAPS) {
 461   methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
 462 
 463   {
 464     Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
 465     Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
 466     while (!stream.at_end()) {
 467       InstanceKlass* ik = stream.method()->method_holder();
 468       if (ik != stackWalker_klass &&
 469             ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
 470         break;
 471       }
 472 


 532     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", NULL);
 533   }
 534 
 535   // Return normally
 536   return (oop)result.get_jobject();
 537 }
 538 
 539 // Walk the next batch of stack frames
 540 //
 541 // Parameters:
 542 //   stackStream    StackStream object
 543 //   mode           Stack walking mode.
 544 //   magic          Must be valid value to continue the stack walk
 545 //   frame_count    Number of frames to be decoded.
 546 //   start_index    Start index to the user-supplied buffers.
 547 //   frames_array   Buffer to store StackFrame in, starting at start_index.
 548 //
 549 // Returns the end index of frame filled in the buffer.
 550 //
 551 jint StackWalk::fetchNextBatch(Handle stackStream, jlong mode, jlong magic,
 552                                int frame_count, int start_index, 
 553                                objArrayHandle frames_array,
 554                                TRAPS)
 555 {
 556   JavaThread* jt = (JavaThread*)THREAD;
 557   BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array);
 558   if (existing_stream == NULL) {
 559     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
 560   }
 561 
 562   if (frames_array.is_null()) {
 563     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", 0L);
 564   }
 565 
 566   log_debug(stackwalk)("StackWalk::fetchNextBatch frame_count %d existing_stream "
 567                        PTR_FORMAT " start %d frames %d",
 568                        frame_count, p2i(existing_stream), start_index, frames_array->length());
 569   int end_index = start_index;
 570   if (frame_count <= 0) {
 571     return end_index;        // No operation.
 572   }
 573 
 574   int count = frame_count + start_index;
 575   assert (frames_array->length() >= count, "not enough space in buffers");
 576 
 577   BaseFrameStream& stream = (*existing_stream);
 578   if (!stream.at_end()) {
 579     stream.next(); // advance past the last frame decoded in previous batch
 580     if (!stream.at_end()) {
 581       int n = fill_in_frames(mode, stream, frame_count, start_index,
 582                              frames_array, end_index, CHECK_0);
 583       if (n < 1) {
 584         THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
 585       }
 586       return end_index;
 587     }
 588   }
 589   return end_index;
 590 }
 591 
 592 void StackWalk::setContinuation(Handle stackStream, jlong magic, objArrayHandle frames_array, Handle cont, TRAPS) {
 593   JavaThread* jt = (JavaThread*)THREAD;
 594 
 595   if (frames_array.is_null()) {
 596     THROW_MSG(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL");
 597   }
 598 
 599   BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array);
 600   if (existing_stream == NULL) {
 601     THROW_MSG(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers");
 602   }
 603 
 604   existing_stream->set_continuation(cont);
 605 }
< prev index next >