< prev index next >

src/hotspot/share/prims/stackwalk.cpp

Print this page

 34 #include "oops/objArrayOop.inline.hpp"
 35 #include "oops/oop.inline.hpp"
 36 #include "prims/stackwalk.hpp"
 37 #include "runtime/continuationJavaClasses.inline.hpp"
 38 #include "runtime/globals.hpp"
 39 #include "runtime/handles.inline.hpp"
 40 #include "runtime/javaCalls.hpp"
 41 #include "runtime/javaThread.hpp"
 42 #include "runtime/keepStackGCProcessed.hpp"
 43 #include "runtime/stackWatermarkSet.hpp"
 44 #include "runtime/vframe.inline.hpp"
 45 #include "utilities/formatBuffer.hpp"
 46 #include "utilities/globalDefinitions.hpp"
 47 
 48 // setup and cleanup actions
 49 BaseFrameStream::BaseFrameStream(JavaThread* thread, Handle continuation)
 50   : _thread(thread), _continuation(continuation), _anchor(0L) {
 51     assert(thread != nullptr, "");
 52 }
 53 
 54 void BaseFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
 55   frames_array->obj_at_put(magic_pos, _thread->threadObj());
 56   _anchor = address_value();
 57   assert(check_magic(frames_array), "invalid magic");
 58 }
 59 
 60 bool BaseFrameStream::check_magic(objArrayHandle frames_array) {
 61   oop   m1 = frames_array->obj_at(magic_pos);
 62   jlong m2 = _anchor;
 63   if (m1 == _thread->threadObj() && m2 == address_value())  return true;
 64   return false;
 65 }
 66 
 67 bool BaseFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) {
 68   bool ok = check_magic(frames_array);
 69   frames_array->obj_at_put(magic_pos, nullptr);
 70   _anchor = 0L;
 71   return ok;
 72 }
 73 
 74 void BaseFrameStream::set_continuation(Handle cont) {
 75   // ensure that the lifetime of the handle is that of the entire walk
 76   // This actually also sets a copy of the handle in the RegisterMap,
 77   // but that's OK, because we want them to be the same, anyway.
 78   // (although we don't rely on this sharing, and set the other copy again)
 79   _continuation.replace(cont());
 80 }
 81 
 82 JavaFrameStream::JavaFrameStream(JavaThread* thread, jint mode, Handle cont_scope, Handle cont)
 83   : BaseFrameStream(thread, cont),
 84    _vfst(cont.is_null()
 85       ? vframeStream(thread, cont_scope)
 86       : vframeStream(cont(), cont_scope)) {
 87   _need_method_info = StackWalk::need_method_info(mode);

115     if (_cont_scope.not_null() && scope == _cont_scope()) {
116       _jvf = nullptr;
117       return;
118     }
119     _cont_entry = _cont_entry->parent();
120   }
121   assert(!Continuation::is_scope_bottom(_cont_scope(), _jvf->fr(), _jvf->register_map()), "");
122 
123   _jvf = _jvf->java_sender();
124 }
125 
126 // Returns the BaseFrameStream for the current stack being traversed.
127 //
128 // Parameters:
129 //  thread         Current Java thread.
130 //  magic          Magic value used for each stack walking
131 //  frames_array   User-supplied buffers.  The 0th element is reserved
132 //                 for this BaseFrameStream to use
133 //
134 BaseFrameStream* BaseFrameStream::from_current(JavaThread* thread, jlong magic,
135                                                objArrayHandle frames_array)
136 {
137   oop m1 = frames_array->obj_at(magic_pos);
138   if (m1 != thread->threadObj()) return nullptr;
139   if (magic == 0L)                    return nullptr;
140   BaseFrameStream* stream = (BaseFrameStream*) (intptr_t) magic;
141   if (!stream->is_valid_in(thread, frames_array))   return nullptr;
142   return stream;
143 }
144 
145 // Unpacks one or more frames into user-supplied buffers.
146 // Updates the end index, and returns the number of unpacked frames.
147 // Always start with the existing vfst.method and bci.
148 // Do not call vfst.next to advance over the last returned value.
149 // In other words, do not leave any stale data in the vfst.
150 //
151 // Parameters:
152 //   mode             Restrict which frames to be decoded.
153 //   BaseFrameStream  stream of frames
154 //   buffer_size      Buffer size
155 //   start_index      Start index to the user-supplied buffers.
156 //   frames_array     Buffer to store stack frame information in, starting at start_index.
157 //                    frames array is a ClassFrameInfo[] array when only getting caller
158 //                    reference, and a StackFrameInfo[] array (or derivative)
159 //                    otherwise. It should never be null.
160 //   end_index        End index to the user-supplied buffers with unpacked frames.
161 //
162 // Returns the number of frames whose information was transferred into the buffers.
163 //
164 int StackWalk::fill_in_frames(jint mode, BaseFrameStream& stream,
165                               int buffer_size, int start_index,
166                               objArrayHandle  frames_array,
167                               int& end_index, TRAPS) {
168   log_debug(stackwalk)("fill_in_frames limit=%d start=%d frames length=%d",
169                        buffer_size, start_index, frames_array->length());
170   assert(buffer_size > 0, "invalid buffer_size");
171   assert(buffer_size <= frames_array->length(), "oob");
172 
173   int frames_decoded = 0;
174   for (; !stream.at_end(); stream.next()) {
175     if (stream.continuation() != nullptr && stream.continuation() != stream.reg_map()->cont()) {
176       // The code in StackStreamFactory.java has failed to set the continuation because frameBuffer.isAtBottom()
177       // returns false if the end of a continuation falls precisely at the end of the batch.
178       // By breaking here, we're signalling the Java code to set the continuation to the parent.
179       break;
180     }
181     assert(stream.continuation() == nullptr || stream.continuation() == stream.reg_map()->cont(), "");
182     Method* method = stream.method();
183 
184     if (method == nullptr) continue;
185 
186     // skip hidden frames for default StackWalker option (i.e. SHOW_HIDDEN_FRAMES

194         continue;
195       }
196     }
197 
198     int index = end_index++;
199     log_debug(stackwalk)("  frame %d: %s bci %d", index, stream.method()->external_name(), stream.bci());
200     stream.fill_frame(index, frames_array, methodHandle(THREAD, method), CHECK_0);
201     frames_decoded++;
202 
203     // End a batch on continuation bottom to let the Java side to set the continuation to its parent and continue
204     if (stream.continuation() != nullptr && method->intrinsic_id() == vmIntrinsics::_Continuation_enter) break;
205 
206     if (end_index >= buffer_size)  break;
207   }
208   log_debug(stackwalk)("fill_in_frames returns %d at_end=%d", frames_decoded, stream.at_end());
209 
210   return frames_decoded;
211 }
212 
213 // Fill in the LiveStackFrameInfo at the given index in frames_array
214 void LiveFrameStream::fill_frame(int index, objArrayHandle  frames_array,
215                                  const methodHandle& method, TRAPS) {
216   HandleMark hm(THREAD);
217   Handle stackFrame(THREAD, frames_array->obj_at(index));
218   fill_live_stackframe(stackFrame, method, CHECK);
219 }
220 
221 // Fill in the StackFrameInfo at the given index in frames_array
222 void JavaFrameStream::fill_frame(int index, objArrayHandle  frames_array,
223                                  const methodHandle& method, TRAPS) {
224   if (_need_method_info) {
225     HandleMark hm(THREAD);
226     Handle stackFrame(THREAD, frames_array->obj_at(index));
227     fill_stackframe(stackFrame, method, CHECK);
228   } else {
229     HandleMark hm(THREAD);
230     Handle stackFrame(THREAD, frames_array->obj_at(index));
231     java_lang_ClassFrameInfo::init_class(stackFrame, method);
232   }
233 }
234 
235 // Create and return a LiveStackFrame.PrimitiveSlot (if needed) for the
236 // StackValue at the given index. 'type' is expected to be T_INT, T_LONG,
237 // T_OBJECT, or T_CONFLICT.
238 oop LiveFrameStream::create_primitive_slot_instance(StackValueCollection* values,
239                                                     int i, BasicType type, TRAPS) {
240   Klass* k = vmClasses::LiveStackFrameInfo_klass();
241   InstanceKlass* ik = InstanceKlass::cast(k);
242 

368   }
369 }
370 
371 // Begins stack walking.
372 //
373 // Parameters:
374 //   stackStream    StackStream object
375 //   mode           Stack walking mode.
376 //   skip_frames    Number of frames to be skipped.
377 //   cont_scope     Continuation scope to walk (if not in this scope, we'll walk all the way).
378 //   buffer_size    Buffer size.
379 //   start_index    Start index to the user-supplied buffers.
380 //   frames_array   Buffer to store stack frame info in, starting at start_index.
381 //                  frames array is a ClassFrameInfo[] array when only getting caller
382 //                  reference, and a StackFrameInfo[] array (or derivative)
383 //                  otherwise. It should never be null.
384 //
385 // Returns Object returned from AbstractStackWalker::doStackWalk call.
386 //
387 oop StackWalk::walk(Handle stackStream, jint mode, int skip_frames, Handle cont_scope, Handle cont,
388                     int buffer_size, int start_index, objArrayHandle frames_array,
389                     TRAPS) {
390   ResourceMark rm(THREAD);
391   HandleMark hm(THREAD); // needed to store a continuation in the RegisterMap
392 
393   JavaThread* jt = THREAD;
394   log_debug(stackwalk)("Start walking: mode " INT32_FORMAT_X " skip %d frames, buffer size %d", mode, skip_frames, buffer_size);
395   LogTarget(Debug, stackwalk) lt;
396   if (lt.is_enabled()) {
397     ResourceMark rm(THREAD);
398     LogStream ls(lt);
399     if (cont_scope() != nullptr) {
400       ls.print("cont_scope: ");
401       cont_scope()->print_on(&ls);
402     }
403     ls.cr();
404   }
405 
406   if (frames_array.is_null()) {
407     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is null", nullptr);
408   }
409 
410   // Setup traversal onto my stack.
411   if (live_frame_info(mode)) {
412     RegisterMap regMap = cont.is_null() ? RegisterMap(jt,
413                                                       RegisterMap::UpdateMap::include,
414                                                       RegisterMap::ProcessFrames::include,
415                                                       RegisterMap::WalkContinuation::include)
416                                         : RegisterMap(cont(), RegisterMap::UpdateMap::include);
417     LiveFrameStream stream(jt, &regMap, cont_scope, cont);
418     return fetchFirstBatch(stream, stackStream, mode, skip_frames, buffer_size,
419                            start_index, frames_array, THREAD);
420   } else {
421     JavaFrameStream stream(jt, mode, cont_scope, cont);
422     return fetchFirstBatch(stream, stackStream, mode, skip_frames, buffer_size,
423                            start_index, frames_array, THREAD);
424   }
425 }
426 
427 oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
428                                jint mode, int skip_frames, int buffer_size,
429                                int start_index, objArrayHandle frames_array, TRAPS) {
430   methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
431 
432   {
433     Klass* stackWalker_klass = vmClasses::StackWalker_klass();
434     Klass* abstractStackWalker_klass = vmClasses::AbstractStackWalker_klass();
435     while (!stream.at_end()) {
436       InstanceKlass* ik = stream.method()->method_holder();
437       if (ik != stackWalker_klass &&
438             ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
439         break;
440       }
441       log_debug(stackwalk)("  skip %s", stream.method()->external_name());
442       stream.next();
443     }
444 
445     // stack frame has been traversed individually and resume stack walk
446     // from the stack frame at depth == skip_frames.
447     for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
448       log_debug(stackwalk)("  skip %s", stream.method()->external_name());
449     }

489 
490   // Return normally
491   return result.get_oop();
492 }
493 
494 // Walk the next batch of stack frames
495 //
496 // Parameters:
497 //   stackStream    StackStream object
498 //   mode           Stack walking mode.
499 //   magic          Must be valid value to continue the stack walk
500 //   last_batch_count Number of frames fetched in the last batch.
501 //   buffer_size    Buffer size.
502 //   start_index    Start index to the user-supplied buffers.
503 //   frames_array   Buffer to store StackFrame in, starting at start_index.
504 //
505 // Returns the number of frames filled in the buffer.
506 //
507 jint StackWalk::fetchNextBatch(Handle stackStream, jint mode, jlong magic,
508                                int last_batch_count, int buffer_size, int start_index,
509                                objArrayHandle frames_array,
510                                TRAPS)
511 {
512   JavaThread* jt = THREAD;
513   BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array);
514   if (existing_stream == nullptr) {
515     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
516   }
517 
518   if (frames_array.is_null()) {
519     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is null", 0L);
520   }
521 
522   log_debug(stackwalk)("StackWalk::fetchNextBatch last_batch_count %d buffer_size %d existing_stream "
523                        PTR_FORMAT " start %d", last_batch_count,
524                        buffer_size, p2i(existing_stream), start_index);
525   int end_index = start_index;
526   if (buffer_size <= start_index) {
527     return 0;        // No operation.
528   }
529 

546       // It is not always safe to dig out the name of the last frame
547       // here, i.e. stream.method()->external_name(), since it may
548       // have been reclaimed by HandleMark::pop_and_restore() together
549       // with the rest of the previous batch.
550       log_debug(stackwalk)("advanced past last frame decoded in the previous batch");
551       stream.next();
552     }
553 
554     if (!stream.at_end()) {
555       int numFrames = fill_in_frames(mode, stream, buffer_size, start_index,
556                              frames_array, end_index, CHECK_0);
557       if (numFrames < 1 && !skip_hidden_frames(mode)) {
558         THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
559       }
560       return numFrames;
561     }
562   }
563   return 0;
564 }
565 
566 void StackWalk::setContinuation(Handle stackStream, jlong magic, objArrayHandle frames_array, Handle cont, TRAPS) {
567   JavaThread* jt = JavaThread::cast(THREAD);
568 
569   if (frames_array.is_null()) {
570     THROW_MSG(vmSymbols::java_lang_NullPointerException(), "frames_array is null");
571   }
572 
573   BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array);
574   if (existing_stream == nullptr) {
575     THROW_MSG(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers");
576   }
577 
578   existing_stream->set_continuation(cont);
579 }

 34 #include "oops/objArrayOop.inline.hpp"
 35 #include "oops/oop.inline.hpp"
 36 #include "prims/stackwalk.hpp"
 37 #include "runtime/continuationJavaClasses.inline.hpp"
 38 #include "runtime/globals.hpp"
 39 #include "runtime/handles.inline.hpp"
 40 #include "runtime/javaCalls.hpp"
 41 #include "runtime/javaThread.hpp"
 42 #include "runtime/keepStackGCProcessed.hpp"
 43 #include "runtime/stackWatermarkSet.hpp"
 44 #include "runtime/vframe.inline.hpp"
 45 #include "utilities/formatBuffer.hpp"
 46 #include "utilities/globalDefinitions.hpp"
 47 
 48 // setup and cleanup actions
 49 BaseFrameStream::BaseFrameStream(JavaThread* thread, Handle continuation)
 50   : _thread(thread), _continuation(continuation), _anchor(0L) {
 51     assert(thread != nullptr, "");
 52 }
 53 
 54 void BaseFrameStream::setup_magic_on_entry(refArrayHandle frames_array) {
 55   frames_array->obj_at_put(magic_pos, _thread->threadObj());
 56   _anchor = address_value();
 57   assert(check_magic(frames_array), "invalid magic");
 58 }
 59 
 60 bool BaseFrameStream::check_magic(refArrayHandle frames_array) {
 61   oop   m1 = frames_array->obj_at(magic_pos);
 62   jlong m2 = _anchor;
 63   if (m1 == _thread->threadObj() && m2 == address_value())  return true;
 64   return false;
 65 }
 66 
 67 bool BaseFrameStream::cleanup_magic_on_exit(refArrayHandle frames_array) {
 68   bool ok = check_magic(frames_array);
 69   frames_array->obj_at_put(magic_pos, nullptr);
 70   _anchor = 0L;
 71   return ok;
 72 }
 73 
 74 void BaseFrameStream::set_continuation(Handle cont) {
 75   // ensure that the lifetime of the handle is that of the entire walk
 76   // This actually also sets a copy of the handle in the RegisterMap,
 77   // but that's OK, because we want them to be the same, anyway.
 78   // (although we don't rely on this sharing, and set the other copy again)
 79   _continuation.replace(cont());
 80 }
 81 
 82 JavaFrameStream::JavaFrameStream(JavaThread* thread, jint mode, Handle cont_scope, Handle cont)
 83   : BaseFrameStream(thread, cont),
 84    _vfst(cont.is_null()
 85       ? vframeStream(thread, cont_scope)
 86       : vframeStream(cont(), cont_scope)) {
 87   _need_method_info = StackWalk::need_method_info(mode);

115     if (_cont_scope.not_null() && scope == _cont_scope()) {
116       _jvf = nullptr;
117       return;
118     }
119     _cont_entry = _cont_entry->parent();
120   }
121   assert(!Continuation::is_scope_bottom(_cont_scope(), _jvf->fr(), _jvf->register_map()), "");
122 
123   _jvf = _jvf->java_sender();
124 }
125 
126 // Returns the BaseFrameStream for the current stack being traversed.
127 //
128 // Parameters:
129 //  thread         Current Java thread.
130 //  magic          Magic value used for each stack walking
131 //  frames_array   User-supplied buffers.  The 0th element is reserved
132 //                 for this BaseFrameStream to use
133 //
134 BaseFrameStream* BaseFrameStream::from_current(JavaThread* thread, jlong magic,
135                                                refArrayHandle frames_array)
136 {
137   oop m1 = frames_array->obj_at(magic_pos);
138   if (m1 != thread->threadObj()) return nullptr;
139   if (magic == 0L)                    return nullptr;
140   BaseFrameStream* stream = (BaseFrameStream*) (intptr_t) magic;
141   if (!stream->is_valid_in(thread, frames_array))   return nullptr;
142   return stream;
143 }
144 
145 // Unpacks one or more frames into user-supplied buffers.
146 // Updates the end index, and returns the number of unpacked frames.
147 // Always start with the existing vfst.method and bci.
148 // Do not call vfst.next to advance over the last returned value.
149 // In other words, do not leave any stale data in the vfst.
150 //
151 // Parameters:
152 //   mode             Restrict which frames to be decoded.
153 //   BaseFrameStream  stream of frames
154 //   buffer_size      Buffer size
155 //   start_index      Start index to the user-supplied buffers.
156 //   frames_array     Buffer to store stack frame information in, starting at start_index.
157 //                    frames array is a ClassFrameInfo[] array when only getting caller
158 //                    reference, and a StackFrameInfo[] array (or derivative)
159 //                    otherwise. It should never be null.
160 //   end_index        End index to the user-supplied buffers with unpacked frames.
161 //
162 // Returns the number of frames whose information was transferred into the buffers.
163 //
164 int StackWalk::fill_in_frames(jint mode, BaseFrameStream& stream,
165                               int buffer_size, int start_index,
166                               refArrayHandle frames_array,
167                               int& end_index, TRAPS) {
168   log_debug(stackwalk)("fill_in_frames limit=%d start=%d frames length=%d",
169                        buffer_size, start_index, frames_array->length());
170   assert(buffer_size > 0, "invalid buffer_size");
171   assert(buffer_size <= frames_array->length(), "oob");
172 
173   int frames_decoded = 0;
174   for (; !stream.at_end(); stream.next()) {
175     if (stream.continuation() != nullptr && stream.continuation() != stream.reg_map()->cont()) {
176       // The code in StackStreamFactory.java has failed to set the continuation because frameBuffer.isAtBottom()
177       // returns false if the end of a continuation falls precisely at the end of the batch.
178       // By breaking here, we're signalling the Java code to set the continuation to the parent.
179       break;
180     }
181     assert(stream.continuation() == nullptr || stream.continuation() == stream.reg_map()->cont(), "");
182     Method* method = stream.method();
183 
184     if (method == nullptr) continue;
185 
186     // skip hidden frames for default StackWalker option (i.e. SHOW_HIDDEN_FRAMES

194         continue;
195       }
196     }
197 
198     int index = end_index++;
199     log_debug(stackwalk)("  frame %d: %s bci %d", index, stream.method()->external_name(), stream.bci());
200     stream.fill_frame(index, frames_array, methodHandle(THREAD, method), CHECK_0);
201     frames_decoded++;
202 
203     // End a batch on continuation bottom to let the Java side to set the continuation to its parent and continue
204     if (stream.continuation() != nullptr && method->intrinsic_id() == vmIntrinsics::_Continuation_enter) break;
205 
206     if (end_index >= buffer_size)  break;
207   }
208   log_debug(stackwalk)("fill_in_frames returns %d at_end=%d", frames_decoded, stream.at_end());
209 
210   return frames_decoded;
211 }
212 
213 // Fill in the LiveStackFrameInfo at the given index in frames_array
214 void LiveFrameStream::fill_frame(int index, refArrayHandle frames_array,
215                                  const methodHandle& method, TRAPS) {
216   HandleMark hm(THREAD);
217   Handle stackFrame(THREAD, frames_array->obj_at(index));
218   fill_live_stackframe(stackFrame, method, CHECK);
219 }
220 
221 // Fill in the StackFrameInfo at the given index in frames_array
222 void JavaFrameStream::fill_frame(int index, refArrayHandle frames_array,
223                                  const methodHandle& method, TRAPS) {
224   if (_need_method_info) {
225     HandleMark hm(THREAD);
226     Handle stackFrame(THREAD, frames_array->obj_at(index));
227     fill_stackframe(stackFrame, method, CHECK);
228   } else {
229     HandleMark hm(THREAD);
230     Handle stackFrame(THREAD, frames_array->obj_at(index));
231     java_lang_ClassFrameInfo::init_class(stackFrame, method);
232   }
233 }
234 
235 // Create and return a LiveStackFrame.PrimitiveSlot (if needed) for the
236 // StackValue at the given index. 'type' is expected to be T_INT, T_LONG,
237 // T_OBJECT, or T_CONFLICT.
238 oop LiveFrameStream::create_primitive_slot_instance(StackValueCollection* values,
239                                                     int i, BasicType type, TRAPS) {
240   Klass* k = vmClasses::LiveStackFrameInfo_klass();
241   InstanceKlass* ik = InstanceKlass::cast(k);
242 

368   }
369 }
370 
371 // Begins stack walking.
372 //
373 // Parameters:
374 //   stackStream    StackStream object
375 //   mode           Stack walking mode.
376 //   skip_frames    Number of frames to be skipped.
377 //   cont_scope     Continuation scope to walk (if not in this scope, we'll walk all the way).
378 //   buffer_size    Buffer size.
379 //   start_index    Start index to the user-supplied buffers.
380 //   frames_array   Buffer to store stack frame info in, starting at start_index.
381 //                  frames array is a ClassFrameInfo[] array when only getting caller
382 //                  reference, and a StackFrameInfo[] array (or derivative)
383 //                  otherwise. It should never be null.
384 //
385 // Returns Object returned from AbstractStackWalker::doStackWalk call.
386 //
387 oop StackWalk::walk(Handle stackStream, jint mode, int skip_frames, Handle cont_scope, Handle cont,
388                     int buffer_size, int start_index, refArrayHandle frames_array,
389                     TRAPS) {
390   ResourceMark rm(THREAD);
391   HandleMark hm(THREAD); // needed to store a continuation in the RegisterMap
392 
393   JavaThread* jt = THREAD;
394   log_debug(stackwalk)("Start walking: mode " INT32_FORMAT_X " skip %d frames, buffer size %d", mode, skip_frames, buffer_size);
395   LogTarget(Debug, stackwalk) lt;
396   if (lt.is_enabled()) {
397     ResourceMark rm(THREAD);
398     LogStream ls(lt);
399     if (cont_scope() != nullptr) {
400       ls.print("cont_scope: ");
401       cont_scope()->print_on(&ls);
402     }
403     ls.cr();
404   }
405 
406   if (frames_array.is_null()) {
407     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is null", nullptr);
408   }
409 
410   // Setup traversal onto my stack.
411   if (live_frame_info(mode)) {
412     RegisterMap regMap = cont.is_null() ? RegisterMap(jt,
413                                                       RegisterMap::UpdateMap::include,
414                                                       RegisterMap::ProcessFrames::include,
415                                                       RegisterMap::WalkContinuation::include)
416                                         : RegisterMap(cont(), RegisterMap::UpdateMap::include);
417     LiveFrameStream stream(jt, &regMap, cont_scope, cont);
418     return fetchFirstBatch(stream, stackStream, mode, skip_frames, buffer_size,
419                            start_index, frames_array, THREAD);
420   } else {
421     JavaFrameStream stream(jt, mode, cont_scope, cont);
422     return fetchFirstBatch(stream, stackStream, mode, skip_frames, buffer_size,
423                            start_index, frames_array, THREAD);
424   }
425 }
426 
427 oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
428                                jint mode, int skip_frames, int buffer_size,
429                                int start_index, refArrayHandle frames_array, TRAPS) {
430   methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
431 
432   {
433     Klass* stackWalker_klass = vmClasses::StackWalker_klass();
434     Klass* abstractStackWalker_klass = vmClasses::AbstractStackWalker_klass();
435     while (!stream.at_end()) {
436       InstanceKlass* ik = stream.method()->method_holder();
437       if (ik != stackWalker_klass &&
438             ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass)  {
439         break;
440       }
441       log_debug(stackwalk)("  skip %s", stream.method()->external_name());
442       stream.next();
443     }
444 
445     // stack frame has been traversed individually and resume stack walk
446     // from the stack frame at depth == skip_frames.
447     for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
448       log_debug(stackwalk)("  skip %s", stream.method()->external_name());
449     }

489 
490   // Return normally
491   return result.get_oop();
492 }
493 
494 // Walk the next batch of stack frames
495 //
496 // Parameters:
497 //   stackStream    StackStream object
498 //   mode           Stack walking mode.
499 //   magic          Must be valid value to continue the stack walk
500 //   last_batch_count Number of frames fetched in the last batch.
501 //   buffer_size    Buffer size.
502 //   start_index    Start index to the user-supplied buffers.
503 //   frames_array   Buffer to store StackFrame in, starting at start_index.
504 //
505 // Returns the number of frames filled in the buffer.
506 //
507 jint StackWalk::fetchNextBatch(Handle stackStream, jint mode, jlong magic,
508                                int last_batch_count, int buffer_size, int start_index,
509                                refArrayHandle frames_array,
510                                TRAPS)
511 {
512   JavaThread* jt = THREAD;
513   BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array);
514   if (existing_stream == nullptr) {
515     THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
516   }
517 
518   if (frames_array.is_null()) {
519     THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is null", 0L);
520   }
521 
522   log_debug(stackwalk)("StackWalk::fetchNextBatch last_batch_count %d buffer_size %d existing_stream "
523                        PTR_FORMAT " start %d", last_batch_count,
524                        buffer_size, p2i(existing_stream), start_index);
525   int end_index = start_index;
526   if (buffer_size <= start_index) {
527     return 0;        // No operation.
528   }
529 

546       // It is not always safe to dig out the name of the last frame
547       // here, i.e. stream.method()->external_name(), since it may
548       // have been reclaimed by HandleMark::pop_and_restore() together
549       // with the rest of the previous batch.
550       log_debug(stackwalk)("advanced past last frame decoded in the previous batch");
551       stream.next();
552     }
553 
554     if (!stream.at_end()) {
555       int numFrames = fill_in_frames(mode, stream, buffer_size, start_index,
556                              frames_array, end_index, CHECK_0);
557       if (numFrames < 1 && !skip_hidden_frames(mode)) {
558         THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L);
559       }
560       return numFrames;
561     }
562   }
563   return 0;
564 }
565 
566 void StackWalk::setContinuation(Handle stackStream, jlong magic, refArrayHandle frames_array, Handle cont, TRAPS) {
567   JavaThread* jt = JavaThread::cast(THREAD);
568 
569   if (frames_array.is_null()) {
570     THROW_MSG(vmSymbols::java_lang_NullPointerException(), "frames_array is null");
571   }
572 
573   BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array);
574   if (existing_stream == nullptr) {
575     THROW_MSG(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers");
576   }
577 
578   existing_stream->set_continuation(cont);
579 }
< prev index next >