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, ®Map, 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, ®Map, 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 }
|