1 /* 2 * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "classfile/javaClasses.inline.hpp" 27 #include "classfile/vmClasses.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/klass.inline.hpp" 34 #include "oops/method.inline.hpp" 35 #include "oops/oop.inline.hpp" 36 #include "oops/objArrayOop.inline.hpp" 37 #include "prims/stackwalk.hpp" 38 #include "runtime/continuationJavaClasses.inline.hpp" 39 #include "runtime/globals.hpp" 40 #include "runtime/handles.inline.hpp" 41 #include "runtime/javaCalls.hpp" 42 #include "runtime/javaThread.hpp" 43 #include "runtime/keepStackGCProcessed.hpp" 44 #include "runtime/stackWatermarkSet.hpp" 45 #include "runtime/vframe.inline.hpp" 46 #include "utilities/formatBuffer.hpp" 47 #include "utilities/globalDefinitions.hpp" 48 49 // setup and cleanup actions 50 BaseFrameStream::BaseFrameStream(JavaThread* thread, Handle continuation) 51 : _thread(thread), _continuation(continuation), _anchor(0L) { 52 assert(thread != nullptr, ""); 53 } 54 55 void BaseFrameStream::setup_magic_on_entry(objArrayHandle frames_array) { 56 frames_array->obj_at_put(magic_pos, _thread->threadObj()); 57 _anchor = address_value(); 58 assert(check_magic(frames_array), "invalid magic"); 59 } 60 61 bool BaseFrameStream::check_magic(objArrayHandle frames_array) { 62 oop m1 = frames_array->obj_at(magic_pos); 63 jlong m2 = _anchor; 64 if (m1 == _thread->threadObj() && m2 == address_value()) return true; 65 return false; 66 } 67 68 bool BaseFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) { 69 bool ok = check_magic(frames_array); 70 frames_array->obj_at_put(magic_pos, nullptr); 71 _anchor = 0L; 72 return ok; 73 } 74 75 void BaseFrameStream::set_continuation(Handle cont) { 76 // ensure that the lifetime of the handle is that of the entire walk 77 // This actually also sets a copy of the handle in the RegisterMap, 78 // but that's OK, because we want them to be the same, anyway. 79 // (although we don't rely on this sharing, and set the other copy again) 80 _continuation.replace(cont()); 81 } 82 83 JavaFrameStream::JavaFrameStream(JavaThread* thread, int mode, Handle cont_scope, Handle cont) 84 : BaseFrameStream(thread, cont), 85 _vfst(cont.is_null() 86 ? vframeStream(thread, cont_scope) 87 : vframeStream(cont(), cont_scope)) { 88 _need_method_info = StackWalk::need_method_info(mode); 89 } 90 91 LiveFrameStream::LiveFrameStream(JavaThread* thread, RegisterMap* rm, Handle cont_scope, Handle cont) 92 : BaseFrameStream(thread, cont), _cont_scope(cont_scope) { 93 94 _map = rm; 95 if (cont.is_null()) { 96 _jvf = thread->last_java_vframe(rm); 97 _cont_entry = thread->last_continuation(); 98 } else { 99 _jvf = Continuation::last_java_vframe(cont, rm); 100 _cont_entry = nullptr; 101 } 102 } 103 104 void JavaFrameStream::next() { 105 _vfst.next(); 106 if (_vfst.method()->is_continuation_enter_intrinsic()) 107 _vfst.next(); 108 } 109 110 void LiveFrameStream::next() { 111 assert(_cont_scope.is_null() || cont() != (oop)nullptr, "must be"); 112 113 oop cont = this->cont(); 114 if (cont != (oop)nullptr && Continuation::is_continuation_entry_frame(_jvf->fr(), _jvf->register_map())) { 115 oop scope = jdk_internal_vm_Continuation::scope(cont); 116 if (_cont_scope.not_null() && scope == _cont_scope()) { 117 _jvf = nullptr; 118 return; 119 } 120 _cont_entry = _cont_entry->parent(); 121 } 122 assert(!Continuation::is_scope_bottom(_cont_scope(), _jvf->fr(), _jvf->register_map()), ""); 123 124 _jvf = _jvf->java_sender(); 125 } 126 127 // Returns the BaseFrameStream for the current stack being traversed. 128 // 129 // Parameters: 130 // thread Current Java thread. 131 // magic Magic value used for each stack walking 132 // frames_array User-supplied buffers. The 0th element is reserved 133 // for this BaseFrameStream to use 134 // 135 BaseFrameStream* BaseFrameStream::from_current(JavaThread* thread, jlong magic, 136 objArrayHandle frames_array) 137 { 138 oop m1 = frames_array->obj_at(magic_pos); 139 if (m1 != thread->threadObj()) return nullptr; 140 if (magic == 0L) return nullptr; 141 BaseFrameStream* stream = (BaseFrameStream*) (intptr_t) magic; 142 if (!stream->is_valid_in(thread, frames_array)) return nullptr; 143 return stream; 144 } 145 146 // Unpacks one or more frames into user-supplied buffers. 147 // Updates the end index, and returns the number of unpacked frames. 148 // Always start with the existing vfst.method and bci. 149 // Do not call vfst.next to advance over the last returned value. 150 // In other words, do not leave any stale data in the vfst. 151 // 152 // Parameters: 153 // mode Restrict which frames to be decoded. 154 // BaseFrameStream stream of frames 155 // max_nframes Maximum number of frames to be filled. 156 // start_index Start index to the user-supplied buffers. 157 // frames_array Buffer to store Class or StackFrame in, starting at start_index. 158 // frames array is a Class<?>[] array when only getting caller 159 // reference, and a StackFrameInfo[] array (or derivative) 160 // otherwise. It should never be null. 161 // end_index End index to the user-supplied buffers with unpacked frames. 162 // 163 // Returns the number of frames whose information was transferred into the buffers. 164 // 165 int StackWalk::fill_in_frames(jlong mode, BaseFrameStream& stream, 166 int max_nframes, int start_index, 167 objArrayHandle frames_array, 168 int& end_index, TRAPS) { 169 log_debug(stackwalk)("fill_in_frames limit=%d start=%d frames length=%d", 170 max_nframes, start_index, frames_array->length()); 171 assert(max_nframes > 0, "invalid max_nframes"); 172 assert(start_index + max_nframes <= frames_array->length(), "oob"); 173 174 int frames_decoded = 0; 175 for (; !stream.at_end(); stream.next()) { 176 assert(stream.continuation() == nullptr || stream.continuation() == stream.reg_map()->cont(), ""); 177 Method* method = stream.method(); 178 179 if (method == nullptr) continue; 180 181 // skip hidden frames for default StackWalker option (i.e. SHOW_HIDDEN_FRAMES 182 // not set) and when StackWalker::getCallerClass is called 183 if (!ShowHiddenFrames && (skip_hidden_frames(mode) || get_caller_class(mode))) { 184 if (method->is_hidden()) { 185 LogTarget(Debug, stackwalk) lt; 186 if (lt.is_enabled()) { 187 ResourceMark rm(THREAD); 188 LogStream ls(lt); 189 ls.print(" hidden method: "); 190 method->print_short_name(&ls); 191 ls.cr(); 192 } 193 continue; 194 } 195 } 196 197 int index = end_index++; 198 LogTarget(Debug, stackwalk) lt; 199 if (lt.is_enabled()) { 200 ResourceMark rm(THREAD); 201 LogStream ls(lt); 202 ls.print(" %d: frame method: ", index); 203 method->print_short_name(&ls); 204 ls.print_cr(" bci=%d", stream.bci()); 205 } 206 207 if (!need_method_info(mode) && get_caller_class(mode) && 208 index == start_index && method->caller_sensitive()) { 209 ResourceMark rm(THREAD); 210 THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(), 211 err_msg("StackWalker::getCallerClass called from @CallerSensitive '%s' method", 212 method->external_name())); 213 } 214 // fill in StackFrameInfo and initialize MemberName 215 stream.fill_frame(index, frames_array, methodHandle(THREAD, method), CHECK_0); 216 217 if (lt.is_enabled()) { 218 ResourceMark rm(THREAD); 219 LogStream ls(lt); 220 ls.print(" %d: done frame method: ", index); 221 method->print_short_name(&ls); 222 } 223 frames_decoded++; 224 225 // We end a batch on continuation bottom to let the Java side skip top frames of the next one 226 if (stream.continuation() != nullptr && method->intrinsic_id() == vmIntrinsics::_Continuation_enter) break; 227 228 if (frames_decoded >= max_nframes) break; 229 } 230 log_debug(stackwalk)("fill_in_frames done frames_decoded=%d at_end=%d", frames_decoded, stream.at_end()); 231 232 return frames_decoded; 233 } 234 235 // Fill in the LiveStackFrameInfo at the given index in frames_array 236 void LiveFrameStream::fill_frame(int index, objArrayHandle frames_array, 237 const methodHandle& method, TRAPS) { 238 HandleMark hm(THREAD); 239 Handle stackFrame(THREAD, frames_array->obj_at(index)); 240 fill_live_stackframe(stackFrame, method, CHECK); 241 } 242 243 // Fill in the StackFrameInfo at the given index in frames_array 244 void JavaFrameStream::fill_frame(int index, objArrayHandle frames_array, 245 const methodHandle& method, TRAPS) { 246 if (_need_method_info) { 247 HandleMark hm(THREAD); 248 Handle stackFrame(THREAD, frames_array->obj_at(index)); 249 fill_stackframe(stackFrame, method, CHECK); 250 } else { 251 frames_array->obj_at_put(index, method->method_holder()->java_mirror()); 252 } 253 } 254 255 // Create and return a LiveStackFrame.PrimitiveSlot (if needed) for the 256 // StackValue at the given index. 'type' is expected to be T_INT, T_LONG, 257 // T_OBJECT, or T_CONFLICT. 258 oop LiveFrameStream::create_primitive_slot_instance(StackValueCollection* values, 259 int i, BasicType type, TRAPS) { 260 Klass* k = vmClasses::LiveStackFrameInfo_klass(); 261 InstanceKlass* ik = InstanceKlass::cast(k); 262 263 JavaValue result(T_OBJECT); 264 JavaCallArguments args; 265 Symbol* signature = nullptr; 266 267 // ## TODO: type is only available in LocalVariable table, if present. 268 // ## StackValue type is T_INT or T_OBJECT (or converted to T_LONG on 64-bit) 269 switch (type) { 270 case T_INT: 271 args.push_int(values->int_at(i)); 272 signature = vmSymbols::asPrimitive_int_signature(); 273 break; 274 275 case T_LONG: 276 args.push_long(values->long_at(i)); 277 signature = vmSymbols::asPrimitive_long_signature(); 278 break; 279 280 case T_FLOAT: 281 case T_DOUBLE: 282 case T_BYTE: 283 case T_SHORT: 284 case T_CHAR: 285 case T_BOOLEAN: 286 THROW_MSG_(vmSymbols::java_lang_InternalError(), "Unexpected StackValue type", nullptr); 287 288 case T_OBJECT: 289 return values->obj_at(i)(); 290 291 case T_CONFLICT: 292 // put a non-null slot 293 #ifdef _LP64 294 args.push_long(0); 295 signature = vmSymbols::asPrimitive_long_signature(); 296 #else 297 args.push_int(0); 298 signature = vmSymbols::asPrimitive_int_signature(); 299 #endif 300 301 break; 302 303 default: ShouldNotReachHere(); 304 } 305 JavaCalls::call_static(&result, 306 ik, 307 vmSymbols::asPrimitive_name(), 308 signature, 309 &args, 310 CHECK_NULL); 311 return (instanceOop) result.get_oop(); 312 } 313 314 objArrayHandle LiveFrameStream::values_to_object_array(StackValueCollection* values, TRAPS) { 315 objArrayHandle empty; 316 int length = values->size(); 317 objArrayOop array_oop = oopFactory::new_objArray(vmClasses::Object_klass(), 318 length, CHECK_(empty)); 319 objArrayHandle array_h(THREAD, array_oop); 320 for (int i = 0; i < values->size(); i++) { 321 StackValue* st = values->at(i); 322 BasicType type = st->type(); 323 int index = i; 324 #ifdef _LP64 325 if (type != T_OBJECT && type != T_CONFLICT) { 326 intptr_t ret = st->get_int(); // read full 64-bit slot 327 type = T_LONG; // treat as long 328 index--; // undo +1 in StackValueCollection::long_at 329 } 330 #endif 331 oop obj = create_primitive_slot_instance(values, index, type, CHECK_(empty)); 332 if (obj != nullptr) { 333 array_h->obj_at_put(i, obj); 334 } 335 } 336 return array_h; 337 } 338 339 objArrayHandle LiveFrameStream::monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors, TRAPS) { 340 int length = monitors->length(); 341 objArrayOop array_oop = oopFactory::new_objArray(vmClasses::Object_klass(), 342 length, CHECK_(objArrayHandle())); 343 objArrayHandle array_h(THREAD, array_oop); 344 for (int i = 0; i < length; i++) { 345 MonitorInfo* monitor = monitors->at(i); 346 array_h->obj_at_put(i, monitor->owner()); 347 } 348 return array_h; 349 } 350 351 // Fill StackFrameInfo with bci and initialize memberName 352 void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method, TRAPS) { 353 java_lang_StackFrameInfo::set_method_and_bci(stackFrame, method, bci(), cont(), THREAD); 354 } 355 356 // Fill LiveStackFrameInfo with locals, monitors, and expressions 357 void LiveFrameStream::fill_live_stackframe(Handle stackFrame, 358 const methodHandle& method, TRAPS) { 359 fill_stackframe(stackFrame, method, CHECK); 360 if (_jvf != nullptr) { 361 ResourceMark rm(THREAD); 362 HandleMark hm(THREAD); 363 364 StackValueCollection* locals = _jvf->locals(); 365 StackValueCollection* expressions = _jvf->expressions(); 366 GrowableArray<MonitorInfo*>* monitors = _jvf->monitors(); 367 368 int mode = 0; 369 if (_jvf->is_interpreted_frame()) { 370 mode = MODE_INTERPRETED; 371 } else if (_jvf->is_compiled_frame()) { 372 mode = MODE_COMPILED; 373 } 374 375 if (!locals->is_empty()) { 376 objArrayHandle locals_h = values_to_object_array(locals, CHECK); 377 java_lang_LiveStackFrameInfo::set_locals(stackFrame(), locals_h()); 378 } 379 if (!expressions->is_empty()) { 380 objArrayHandle expressions_h = values_to_object_array(expressions, CHECK); 381 java_lang_LiveStackFrameInfo::set_operands(stackFrame(), expressions_h()); 382 } 383 if (monitors->length() > 0) { 384 objArrayHandle monitors_h = monitors_to_object_array(monitors, CHECK); 385 java_lang_LiveStackFrameInfo::set_monitors(stackFrame(), monitors_h()); 386 } 387 java_lang_LiveStackFrameInfo::set_mode(stackFrame(), mode); 388 } 389 } 390 391 // Begins stack walking. 392 // 393 // Parameters: 394 // stackStream StackStream object 395 // mode Stack walking mode. 396 // skip_frames Number of frames to be skipped. 397 // cont_scope Continuation scope to walk (if not in this scope, we'll walk all the way). 398 // frame_count Number of frames to be traversed. 399 // start_index Start index to the user-supplied buffers. 400 // frames_array Buffer to store StackFrame in, starting at start_index. 401 // frames array is a Class<?>[] array when only getting caller 402 // reference, and a StackFrameInfo[] array (or derivative) 403 // otherwise. It should never be null. 404 // 405 // Returns Object returned from AbstractStackWalker::doStackWalk call. 406 // 407 oop StackWalk::walk(Handle stackStream, jlong mode, int skip_frames, Handle cont_scope, Handle cont, 408 int frame_count, int start_index, objArrayHandle frames_array, 409 TRAPS) { 410 ResourceMark rm(THREAD); 411 HandleMark hm(THREAD); // needed to store a continuation in the RegisterMap 412 413 JavaThread* jt = THREAD; 414 log_debug(stackwalk)("Start walking: mode " JLONG_FORMAT " skip %d frames batch size %d", mode, skip_frames, frame_count); 415 LogTarget(Debug, stackwalk) lt; 416 if (lt.is_enabled()) { 417 ResourceMark rm(THREAD); 418 LogStream ls(lt); 419 if (cont_scope() != nullptr) { 420 ls.print("cont_scope: "); 421 cont_scope()->print_on(&ls); 422 } 423 ls.cr(); 424 } 425 426 if (frames_array.is_null()) { 427 THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is null", nullptr); 428 } 429 430 // Setup traversal onto my stack. 431 if (live_frame_info(mode)) { 432 assert(use_frames_array(mode), "Bad mode for get live frame"); 433 RegisterMap regMap = cont.is_null() ? RegisterMap(jt, 434 RegisterMap::UpdateMap::include, 435 RegisterMap::ProcessFrames::include, 436 RegisterMap::WalkContinuation::include) 437 : RegisterMap(cont(), RegisterMap::UpdateMap::include); 438 LiveFrameStream stream(jt, ®Map, cont_scope, cont); 439 return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count, 440 start_index, frames_array, THREAD); 441 } else { 442 JavaFrameStream stream(jt, mode, cont_scope, cont); 443 return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count, 444 start_index, frames_array, THREAD); 445 } 446 } 447 448 oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream, 449 jlong mode, int skip_frames, int frame_count, 450 int start_index, objArrayHandle frames_array, TRAPS) { 451 methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method()); 452 453 { 454 Klass* stackWalker_klass = vmClasses::StackWalker_klass(); 455 Klass* abstractStackWalker_klass = vmClasses::AbstractStackWalker_klass(); 456 while (!stream.at_end()) { 457 InstanceKlass* ik = stream.method()->method_holder(); 458 if (ik != stackWalker_klass && 459 ik != abstractStackWalker_klass && ik->super() != abstractStackWalker_klass) { 460 break; 461 } 462 463 LogTarget(Debug, stackwalk) lt; 464 if (lt.is_enabled()) { 465 ResourceMark rm(THREAD); 466 LogStream ls(lt); 467 ls.print(" skip "); 468 stream.method()->print_short_name(&ls); 469 ls.cr(); 470 } 471 stream.next(); 472 } 473 474 // stack frame has been traversed individually and resume stack walk 475 // from the stack frame at depth == skip_frames. 476 for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) { 477 LogTarget(Debug, stackwalk) lt; 478 if (lt.is_enabled()) { 479 ResourceMark rm(THREAD); 480 LogStream ls(lt); 481 ls.print(" skip "); 482 stream.method()->print_short_name(&ls); 483 ls.cr(); 484 } 485 } 486 } 487 488 int end_index = start_index; 489 int numFrames = 0; 490 if (!stream.at_end()) { 491 KeepStackGCProcessedMark keep_stack(THREAD); 492 numFrames = fill_in_frames(mode, stream, frame_count, start_index, 493 frames_array, end_index, CHECK_NULL); 494 if (numFrames < 1) { 495 THROW_MSG_(vmSymbols::java_lang_InternalError(), "stack walk: decode failed", nullptr); 496 } 497 } 498 499 // JVM_CallStackWalk walks the stack and fills in stack frames, then calls to 500 // Java method java.lang.StackStreamFactory.AbstractStackWalker::doStackWalk 501 // which calls the implementation to consume the stack frames. 502 // When JVM_CallStackWalk returns, it invalidates the stack stream. 503 JavaValue result(T_OBJECT); 504 JavaCallArguments args(stackStream); 505 args.push_long(stream.address_value()); 506 args.push_int(skip_frames); 507 args.push_int(frame_count); 508 args.push_int(start_index); 509 args.push_int(end_index); 510 511 // Link the thread and vframe stream into the callee-visible object 512 stream.setup_magic_on_entry(frames_array); 513 514 JavaCalls::call(&result, m_doStackWalk, &args, THREAD); 515 516 // Do this before anything else happens, to disable any lingering stream objects 517 bool ok = stream.cleanup_magic_on_exit(frames_array); 518 519 // Throw pending exception if we must 520 (void) (CHECK_NULL); 521 522 if (!ok) { 523 THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers on exit", nullptr); 524 } 525 526 // Return normally 527 return result.get_oop(); 528 } 529 530 // Walk the next batch of stack frames 531 // 532 // Parameters: 533 // stackStream StackStream object 534 // mode Stack walking mode. 535 // magic Must be valid value to continue the stack walk 536 // frame_count Number of frames to be decoded. 537 // start_index Start index to the user-supplied buffers. 538 // frames_array Buffer to store StackFrame in, starting at start_index. 539 // 540 // Returns the end index of frame filled in the buffer. 541 // 542 jint StackWalk::fetchNextBatch(Handle stackStream, jlong mode, jlong magic, 543 int frame_count, int start_index, 544 objArrayHandle frames_array, 545 TRAPS) 546 { 547 JavaThread* jt = THREAD; 548 BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array); 549 if (existing_stream == nullptr) { 550 THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L); 551 } 552 553 if (frames_array.is_null()) { 554 THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is null", 0L); 555 } 556 557 log_debug(stackwalk)("StackWalk::fetchNextBatch frame_count %d existing_stream " 558 PTR_FORMAT " start %d frames %d", 559 frame_count, p2i(existing_stream), start_index, frames_array->length()); 560 int end_index = start_index; 561 if (frame_count <= 0) { 562 return end_index; // No operation. 563 } 564 565 int count = frame_count + start_index; 566 assert (frames_array->length() >= count, "not enough space in buffers"); 567 568 BaseFrameStream& stream = (*existing_stream); 569 if (!stream.at_end()) { 570 // If we have to get back here for even more frames, then 1) the user did not supply 571 // an accurate hint suggesting the depth of the stack walk, and 2) we are not just 572 // peeking at a few frames. Take the cost of flushing out any pending deferred GC 573 // processing of the stack. 574 KeepStackGCProcessedMark keep_stack(jt); 575 stream.next(); // advance past the last frame decoded in previous batch 576 if (!stream.at_end()) { 577 int n = fill_in_frames(mode, stream, frame_count, start_index, 578 frames_array, end_index, CHECK_0); 579 if (n < 1) { 580 THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: later decode failed", 0L); 581 } 582 return end_index; 583 } 584 } 585 return end_index; 586 } 587 588 void StackWalk::setContinuation(Handle stackStream, jlong magic, objArrayHandle frames_array, Handle cont, TRAPS) { 589 JavaThread* jt = JavaThread::cast(THREAD); 590 591 if (frames_array.is_null()) { 592 THROW_MSG(vmSymbols::java_lang_NullPointerException(), "frames_array is null"); 593 } 594 595 BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array); 596 if (existing_stream == nullptr) { 597 THROW_MSG(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers"); 598 } 599 600 existing_stream->set_continuation(cont); 601 }