1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/frames.h" 6 7 #include <memory> 8 #include <sstream> 9 10 #include "src/base/bits.h" 11 #include "src/deoptimizer.h" 12 #include "src/frames-inl.h" 13 #include "src/ic/ic-stats.h" 14 #include "src/register-configuration.h" 15 #include "src/safepoint-table.h" 16 #include "src/string-stream.h" 17 #include "src/visitors.h" 18 #include "src/vm-state-inl.h" 19 #include "src/wasm/wasm-code-manager.h" 20 #include "src/wasm/wasm-engine.h" 21 #include "src/wasm/wasm-objects-inl.h" 22 #include "src/zone/zone-containers.h" 23 24 namespace v8 { 25 namespace internal { 26 27 ReturnAddressLocationResolver StackFrame::return_address_location_resolver_ = 28 nullptr; 29 30 // Iterator that supports traversing the stack handlers of a 31 // particular frame. Needs to know the top of the handler chain. 32 class StackHandlerIterator BASE_EMBEDDED { 33 public: 34 StackHandlerIterator(const StackFrame* frame, StackHandler* handler) 35 : limit_(frame->fp()), handler_(handler) { 36 // Make sure the handler has already been unwound to this frame. 37 DCHECK(frame->sp() <= handler->address()); 38 } 39 40 StackHandler* handler() const { return handler_; } 41 42 bool done() { return handler_ == nullptr || handler_->address() > limit_; } 43 void Advance() { 44 DCHECK(!done()); 45 handler_ = handler_->next(); 46 } 47 48 private: 49 const Address limit_; 50 StackHandler* handler_; 51 }; 52 53 54 // ------------------------------------------------------------------------- 55 56 57 #define INITIALIZE_SINGLETON(type, field) field##_(this), 58 StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate, 59 bool can_access_heap_objects) 60 : isolate_(isolate), 61 STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) frame_(nullptr), 62 handler_(nullptr), 63 can_access_heap_objects_(can_access_heap_objects) {} 64 #undef INITIALIZE_SINGLETON 65 66 StackFrameIterator::StackFrameIterator(Isolate* isolate) 67 : StackFrameIterator(isolate, isolate->thread_local_top()) {} 68 69 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) 70 : StackFrameIteratorBase(isolate, true) { 71 Reset(t); 72 } 73 74 void StackFrameIterator::Advance() { 75 DCHECK(!done()); 76 // Compute the state of the calling frame before restoring 77 // callee-saved registers and unwinding handlers. This allows the 78 // frame code that computes the caller state to access the top 79 // handler and the value of any callee-saved register if needed. 80 StackFrame::State state; 81 StackFrame::Type type = frame_->GetCallerState(&state); 82 83 // Unwind handlers corresponding to the current frame. 84 StackHandlerIterator it(frame_, handler_); 85 while (!it.done()) it.Advance(); 86 handler_ = it.handler(); 87 88 // Advance to the calling frame. 89 frame_ = SingletonFor(type, &state); 90 91 // When we're done iterating over the stack frames, the handler 92 // chain must have been completely unwound. 93 DCHECK(!done() || handler_ == nullptr); 94 } 95 96 97 void StackFrameIterator::Reset(ThreadLocalTop* top) { 98 StackFrame::State state; 99 StackFrame::Type type = ExitFrame::GetStateForFramePointer( 100 Isolate::c_entry_fp(top), &state); 101 handler_ = StackHandler::FromAddress(Isolate::handler(top)); 102 frame_ = SingletonFor(type, &state); 103 } 104 105 106 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type, 107 StackFrame::State* state) { 108 StackFrame* result = SingletonFor(type); 109 DCHECK((!result) == (type == StackFrame::NONE)); 110 if (result) result->state_ = *state; 111 return result; 112 } 113 114 115 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) { 116 #define FRAME_TYPE_CASE(type, field) \ 117 case StackFrame::type: \ 118 return &field##_; 119 120 switch (type) { 121 case StackFrame::NONE: 122 return nullptr; 123 STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) 124 default: break; 125 } 126 return nullptr; 127 128 #undef FRAME_TYPE_CASE 129 } 130 131 // ------------------------------------------------------------------------- 132 133 void JavaScriptFrameIterator::Advance() { 134 do { 135 iterator_.Advance(); 136 } while (!iterator_.done() && !iterator_.frame()->is_java_script()); 137 } 138 139 // ------------------------------------------------------------------------- 140 141 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) 142 : iterator_(isolate) { 143 if (!done() && !IsValidFrame(iterator_.frame())) Advance(); 144 } 145 146 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate, 147 StackFrame::Id id) 148 : StackTraceFrameIterator(isolate) { 149 while (!done() && frame()->id() != id) Advance(); 150 } 151 152 void StackTraceFrameIterator::Advance() { 153 do { 154 iterator_.Advance(); 155 } while (!done() && !IsValidFrame(iterator_.frame())); 156 } 157 158 bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const { 159 if (frame->is_java_script()) { 160 JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame); 161 if (!jsFrame->function()->IsJSFunction()) return false; 162 return jsFrame->function()->shared()->IsSubjectToDebugging(); 163 } 164 // apart from javascript, only wasm is valid 165 return frame->is_wasm(); 166 } 167 168 // ------------------------------------------------------------------------- 169 170 namespace { 171 172 bool IsInterpreterFramePc(Isolate* isolate, Address pc, 173 StackFrame::State* state) { 174 Code* interpreter_entry_trampoline = 175 isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline); 176 Code* interpreter_bytecode_advance = 177 isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeAdvance); 178 Code* interpreter_bytecode_dispatch = 179 isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch); 180 181 if (interpreter_entry_trampoline->contains(pc) || 182 interpreter_bytecode_advance->contains(pc) || 183 interpreter_bytecode_dispatch->contains(pc)) { 184 return true; 185 } else if (FLAG_interpreted_frames_native_stack) { 186 intptr_t marker = Memory<intptr_t>( 187 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset); 188 MSAN_MEMORY_IS_INITIALIZED( 189 state->fp + StandardFrameConstants::kFunctionOffset, kPointerSize); 190 Object* maybe_function = 191 Memory<Object*>(state->fp + StandardFrameConstants::kFunctionOffset); 192 // There's no need to run a full ContainsSlow if we know the frame can't be 193 // an InterpretedFrame, so we do these fast checks first 194 if (StackFrame::IsTypeMarker(marker) || maybe_function->IsSmi()) { 195 return false; 196 } else if (!isolate->heap()->code_space()->ContainsSlow(pc)) { 197 return false; 198 } 199 interpreter_entry_trampoline = 200 isolate->heap()->GcSafeFindCodeForInnerPointer(pc); 201 return interpreter_entry_trampoline->is_interpreter_trampoline_builtin(); 202 } else { 203 return false; 204 } 205 } 206 207 DISABLE_ASAN Address ReadMemoryAt(Address address) { 208 return Memory<Address>(address); 209 } 210 211 } // namespace 212 213 SafeStackFrameIterator::SafeStackFrameIterator( 214 Isolate* isolate, 215 Address fp, Address sp, Address js_entry_sp) 216 : StackFrameIteratorBase(isolate, false), 217 low_bound_(sp), 218 high_bound_(js_entry_sp), 219 top_frame_type_(StackFrame::NONE), 220 external_callback_scope_(isolate->external_callback_scope()) { 221 StackFrame::State state; 222 StackFrame::Type type; 223 ThreadLocalTop* top = isolate->thread_local_top(); 224 bool advance_frame = true; 225 if (IsValidTop(top)) { 226 type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); 227 top_frame_type_ = type; 228 } else if (IsValidStackAddress(fp)) { 229 DCHECK_NE(fp, kNullAddress); 230 state.fp = fp; 231 state.sp = sp; 232 state.pc_address = StackFrame::ResolveReturnAddressLocation( 233 reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp))); 234 235 // If the top of stack is a return address to the interpreter trampoline, 236 // then we are likely in a bytecode handler with elided frame. In that 237 // case, set the PC properly and make sure we do not drop the frame. 238 if (IsValidStackAddress(sp)) { 239 MSAN_MEMORY_IS_INITIALIZED(sp, kPointerSize); 240 Address tos = ReadMemoryAt(sp); 241 if (IsInterpreterFramePc(isolate, tos, &state)) { 242 state.pc_address = reinterpret_cast<Address*>(sp); 243 advance_frame = false; 244 } 245 } 246 247 // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, 248 // we check only that kMarkerOffset is within the stack bounds and do 249 // compile time check that kContextOffset slot is pushed on the stack before 250 // kMarkerOffset. 251 STATIC_ASSERT(StandardFrameConstants::kFunctionOffset < 252 StandardFrameConstants::kContextOffset); 253 Address frame_marker = fp + StandardFrameConstants::kFunctionOffset; 254 if (IsValidStackAddress(frame_marker)) { 255 type = StackFrame::ComputeType(this, &state); 256 top_frame_type_ = type; 257 // We only keep the top frame if we believe it to be interpreted frame. 258 if (type != StackFrame::INTERPRETED) { 259 advance_frame = true; 260 } 261 } else { 262 // Mark the frame as OPTIMIZED if we cannot determine its type. 263 // We chose OPTIMIZED rather than INTERPRETED because it's closer to 264 // the original value of StackFrame::JAVA_SCRIPT here, in that JAVA_SCRIPT 265 // referred to full-codegen frames (now removed from the tree), and 266 // OPTIMIZED refers to turbofan frames, both of which are generated 267 // code. INTERPRETED frames refer to bytecode. 268 // The frame anyways will be skipped. 269 type = StackFrame::OPTIMIZED; 270 // Top frame is incomplete so we cannot reliably determine its type. 271 top_frame_type_ = StackFrame::NONE; 272 } 273 } else { 274 return; 275 } 276 frame_ = SingletonFor(type, &state); 277 if (advance_frame && frame_) Advance(); 278 } 279 280 281 bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const { 282 Address c_entry_fp = Isolate::c_entry_fp(top); 283 if (!IsValidExitFrame(c_entry_fp)) return false; 284 // There should be at least one JS_ENTRY stack handler. 285 Address handler = Isolate::handler(top); 286 if (handler == kNullAddress) return false; 287 // Check that there are no js frames on top of the native frames. 288 return c_entry_fp < handler; 289 } 290 291 292 void SafeStackFrameIterator::AdvanceOneFrame() { 293 DCHECK(!done()); 294 StackFrame* last_frame = frame_; 295 Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); 296 // Before advancing to the next stack frame, perform pointer validity tests. 297 if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) { 298 frame_ = nullptr; 299 return; 300 } 301 302 // Advance to the previous frame. 303 StackFrame::State state; 304 StackFrame::Type type = frame_->GetCallerState(&state); 305 frame_ = SingletonFor(type, &state); 306 if (!frame_) return; 307 308 // Check that we have actually moved to the previous frame in the stack. 309 if (frame_->sp() <= last_sp || frame_->fp() <= last_fp) { 310 frame_ = nullptr; 311 } 312 } 313 314 315 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const { 316 return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()); 317 } 318 319 320 bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) { 321 StackFrame::State state; 322 if (frame->is_entry() || frame->is_construct_entry()) { 323 // See EntryFrame::GetCallerState. It computes the caller FP address 324 // and calls ExitFrame::GetStateForFramePointer on it. We need to be 325 // sure that caller FP address is valid. 326 Address caller_fp = 327 Memory<Address>(frame->fp() + EntryFrameConstants::kCallerFPOffset); 328 if (!IsValidExitFrame(caller_fp)) return false; 329 } else if (frame->is_arguments_adaptor()) { 330 // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that 331 // the number of arguments is stored on stack as Smi. We need to check 332 // that it really an Smi. 333 Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)-> 334 GetExpression(0); 335 if (!number_of_args->IsSmi()) { 336 return false; 337 } 338 } 339 frame->ComputeCallerState(&state); 340 return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) && 341 SingletonFor(frame->GetCallerState(&state)) != nullptr; 342 } 343 344 345 bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const { 346 if (!IsValidStackAddress(fp)) return false; 347 Address sp = ExitFrame::ComputeStackPointer(fp); 348 if (!IsValidStackAddress(sp)) return false; 349 StackFrame::State state; 350 ExitFrame::FillState(fp, sp, &state); 351 MSAN_MEMORY_IS_INITIALIZED(state.pc_address, sizeof(state.pc_address)); 352 return *state.pc_address != kNullAddress; 353 } 354 355 356 void SafeStackFrameIterator::Advance() { 357 while (true) { 358 AdvanceOneFrame(); 359 if (done()) break; 360 ExternalCallbackScope* last_callback_scope = nullptr; 361 while (external_callback_scope_ != nullptr && 362 external_callback_scope_->scope_address() < frame_->fp()) { 363 // As long as the setup of a frame is not atomic, we may happen to be 364 // in an interval where an ExternalCallbackScope is already created, 365 // but the frame is not yet entered. So we are actually observing 366 // the previous frame. 367 // Skip all the ExternalCallbackScope's that are below the current fp. 368 last_callback_scope = external_callback_scope_; 369 external_callback_scope_ = external_callback_scope_->previous(); 370 } 371 if (frame_->is_java_script() || frame_->is_wasm()) break; 372 if (frame_->is_exit() || frame_->is_builtin_exit()) { 373 // Some of the EXIT frames may have ExternalCallbackScope allocated on 374 // top of them. In that case the scope corresponds to the first EXIT 375 // frame beneath it. There may be other EXIT frames on top of the 376 // ExternalCallbackScope, just skip them as we cannot collect any useful 377 // information about them. 378 if (last_callback_scope) { 379 frame_->state_.pc_address = 380 last_callback_scope->callback_entrypoint_address(); 381 } 382 break; 383 } 384 } 385 } 386 387 388 // ------------------------------------------------------------------------- 389 390 namespace { 391 Code* GetContainingCode(Isolate* isolate, Address pc) { 392 return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; 393 } 394 } // namespace 395 396 Code* StackFrame::LookupCode() const { 397 Code* result = GetContainingCode(isolate(), pc()); 398 DCHECK_GE(pc(), result->InstructionStart()); 399 DCHECK_LT(pc(), result->InstructionEnd()); 400 return result; 401 } 402 403 void StackFrame::IteratePc(RootVisitor* v, Address* pc_address, 404 Address* constant_pool_address, Code* holder) { 405 Address pc = *pc_address; 406 DCHECK(holder->GetHeap()->GcSafeCodeContains(holder, pc)); 407 unsigned pc_offset = static_cast<unsigned>(pc - holder->InstructionStart()); 408 Object* code = holder; 409 v->VisitRootPointer(Root::kTop, nullptr, &code); 410 if (code == holder) return; 411 holder = reinterpret_cast<Code*>(code); 412 pc = holder->InstructionStart() + pc_offset; 413 *pc_address = pc; 414 if (FLAG_enable_embedded_constant_pool && constant_pool_address) { 415 *constant_pool_address = holder->constant_pool(); 416 } 417 } 418 419 420 void StackFrame::SetReturnAddressLocationResolver( 421 ReturnAddressLocationResolver resolver) { 422 DCHECK_NULL(return_address_location_resolver_); 423 return_address_location_resolver_ = resolver; 424 } 425 426 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, 427 State* state) { 428 DCHECK_NE(state->fp, kNullAddress); 429 430 MSAN_MEMORY_IS_INITIALIZED( 431 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset, 432 kPointerSize); 433 intptr_t marker = Memory<intptr_t>( 434 state->fp + CommonFrameConstants::kContextOrFrameTypeOffset); 435 if (!iterator->can_access_heap_objects_) { 436 // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really 437 // means that we are being called from the profiler, which can interrupt 438 // the VM with a signal at any arbitrary instruction, with essentially 439 // anything on the stack. So basically none of these checks are 100% 440 // reliable. 441 MSAN_MEMORY_IS_INITIALIZED( 442 state->fp + StandardFrameConstants::kFunctionOffset, kPointerSize); 443 Object* maybe_function = 444 Memory<Object*>(state->fp + StandardFrameConstants::kFunctionOffset); 445 if (!StackFrame::IsTypeMarker(marker)) { 446 if (maybe_function->IsSmi()) { 447 return NATIVE; 448 } else if (IsInterpreterFramePc(iterator->isolate(), *(state->pc_address), 449 state)) { 450 return INTERPRETED; 451 } else { 452 return OPTIMIZED; 453 } 454 } 455 } else { 456 Address pc = *(state->pc_address); 457 // If the {pc} does not point into WebAssembly code we can rely on the 458 // returned {wasm_code} to be null and fall back to {GetContainingCode}. 459 wasm::WasmCode* wasm_code = 460 iterator->isolate()->wasm_engine()->code_manager()->LookupCode(pc); 461 if (wasm_code != nullptr) { 462 switch (wasm_code->kind()) { 463 case wasm::WasmCode::kFunction: 464 return WASM_COMPILED; 465 case wasm::WasmCode::kWasmToJsWrapper: 466 return WASM_TO_JS; 467 case wasm::WasmCode::kLazyStub: 468 return WASM_COMPILE_LAZY; 469 case wasm::WasmCode::kRuntimeStub: 470 return STUB; 471 case wasm::WasmCode::kInterpreterEntry: 472 return WASM_INTERPRETER_ENTRY; 473 default: 474 UNREACHABLE(); 475 } 476 } else { 477 // Look up the code object to figure out the type of the stack frame. 478 Code* code_obj = GetContainingCode(iterator->isolate(), pc); 479 if (code_obj != nullptr) { 480 switch (code_obj->kind()) { 481 case Code::BUILTIN: 482 if (StackFrame::IsTypeMarker(marker)) break; 483 if (code_obj->is_interpreter_trampoline_builtin()) { 484 return INTERPRETED; 485 } 486 if (code_obj->is_turbofanned()) { 487 // TODO(bmeurer): We treat frames for BUILTIN Code objects as 488 // OptimizedFrame for now (all the builtins with JavaScript 489 // linkage are actually generated with TurboFan currently, so 490 // this is sound). 491 return OPTIMIZED; 492 } 493 return BUILTIN; 494 case Code::OPTIMIZED_FUNCTION: 495 return OPTIMIZED; 496 case Code::WASM_FUNCTION: 497 return WASM_COMPILED; 498 case Code::WASM_TO_JS_FUNCTION: 499 return WASM_TO_JS; 500 case Code::JS_TO_WASM_FUNCTION: 501 return JS_TO_WASM; 502 case Code::WASM_INTERPRETER_ENTRY: 503 return WASM_INTERPRETER_ENTRY; 504 case Code::C_WASM_ENTRY: 505 return C_WASM_ENTRY; 506 default: 507 // All other types should have an explicit marker 508 break; 509 } 510 } else { 511 return NATIVE; 512 } 513 } 514 } 515 DCHECK(StackFrame::IsTypeMarker(marker)); 516 StackFrame::Type candidate = StackFrame::MarkerToType(marker); 517 switch (candidate) { 518 case ENTRY: 519 case CONSTRUCT_ENTRY: 520 case EXIT: 521 case BUILTIN_CONTINUATION: 522 case JAVA_SCRIPT_BUILTIN_CONTINUATION: 523 case JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH: 524 case BUILTIN_EXIT: 525 case STUB: 526 case INTERNAL: 527 case CONSTRUCT: 528 case ARGUMENTS_ADAPTOR: 529 case WASM_TO_JS: 530 case WASM_COMPILED: 531 return candidate; 532 case JS_TO_WASM: 533 case OPTIMIZED: 534 case INTERPRETED: 535 default: 536 // Unoptimized and optimized JavaScript frames, including 537 // interpreted frames, should never have a StackFrame::Type 538 // marker. If we find one, we're likely being called from the 539 // profiler in a bogus stack frame. 540 return NATIVE; 541 } 542 } 543 544 545 #ifdef DEBUG 546 bool StackFrame::can_access_heap_objects() const { 547 return iterator_->can_access_heap_objects_; 548 } 549 #endif 550 551 552 StackFrame::Type StackFrame::GetCallerState(State* state) const { 553 ComputeCallerState(state); 554 return ComputeType(iterator_, state); 555 } 556 557 558 Address StackFrame::UnpaddedFP() const { 559 return fp(); 560 } 561 562 void NativeFrame::ComputeCallerState(State* state) const { 563 state->sp = caller_sp(); 564 state->fp = Memory<Address>(fp() + CommonFrameConstants::kCallerFPOffset); 565 state->pc_address = ResolveReturnAddressLocation( 566 reinterpret_cast<Address*>(fp() + CommonFrameConstants::kCallerPCOffset)); 567 state->callee_pc_address = nullptr; 568 state->constant_pool_address = nullptr; 569 } 570 571 Code* EntryFrame::unchecked_code() const { 572 return isolate()->heap()->js_entry_code(); 573 } 574 575 576 void EntryFrame::ComputeCallerState(State* state) const { 577 GetCallerState(state); 578 } 579 580 581 StackFrame::Type EntryFrame::GetCallerState(State* state) const { 582 const int offset = EntryFrameConstants::kCallerFPOffset; 583 Address fp = Memory<Address>(this->fp() + offset); 584 return ExitFrame::GetStateForFramePointer(fp, state); 585 } 586 587 Code* ConstructEntryFrame::unchecked_code() const { 588 return isolate()->heap()->js_construct_entry_code(); 589 } 590 591 592 Object*& ExitFrame::code_slot() const { 593 const int offset = ExitFrameConstants::kCodeOffset; 594 return Memory<Object*>(fp() + offset); 595 } 596 597 Code* ExitFrame::unchecked_code() const { 598 return reinterpret_cast<Code*>(code_slot()); 599 } 600 601 602 void ExitFrame::ComputeCallerState(State* state) const { 603 // Set up the caller state. 604 state->sp = caller_sp(); 605 state->fp = Memory<Address>(fp() + ExitFrameConstants::kCallerFPOffset); 606 state->pc_address = ResolveReturnAddressLocation( 607 reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset)); 608 state->callee_pc_address = nullptr; 609 if (FLAG_enable_embedded_constant_pool) { 610 state->constant_pool_address = reinterpret_cast<Address*>( 611 fp() + ExitFrameConstants::kConstantPoolOffset); 612 } 613 } 614 615 616 void ExitFrame::Iterate(RootVisitor* v) const { 617 // The arguments are traversed as part of the expression stack of 618 // the calling frame. 619 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 620 v->VisitRootPointer(Root::kTop, nullptr, &code_slot()); 621 } 622 623 624 Address ExitFrame::GetCallerStackPointer() const { 625 return fp() + ExitFrameConstants::kCallerSPOffset; 626 } 627 628 629 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { 630 if (fp == 0) return NONE; 631 Address sp = ComputeStackPointer(fp); 632 FillState(fp, sp, state); 633 DCHECK_NE(*state->pc_address, kNullAddress); 634 635 return ComputeFrameType(fp); 636 } 637 638 StackFrame::Type ExitFrame::ComputeFrameType(Address fp) { 639 // Distinguish between between regular and builtin exit frames. 640 // Default to EXIT in all hairy cases (e.g., when called from profiler). 641 const int offset = ExitFrameConstants::kFrameTypeOffset; 642 Object* marker = Memory<Object*>(fp + offset); 643 644 if (!marker->IsSmi()) { 645 return EXIT; 646 } 647 648 intptr_t marker_int = bit_cast<intptr_t>(marker); 649 650 StackFrame::Type frame_type = static_cast<StackFrame::Type>(marker_int >> 1); 651 if (frame_type == EXIT || frame_type == BUILTIN_EXIT) { 652 return frame_type; 653 } 654 655 return EXIT; 656 } 657 658 Address ExitFrame::ComputeStackPointer(Address fp) { 659 MSAN_MEMORY_IS_INITIALIZED(fp + ExitFrameConstants::kSPOffset, kPointerSize); 660 return Memory<Address>(fp + ExitFrameConstants::kSPOffset); 661 } 662 663 void ExitFrame::FillState(Address fp, Address sp, State* state) { 664 state->sp = sp; 665 state->fp = fp; 666 state->pc_address = ResolveReturnAddressLocation( 667 reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize)); 668 state->callee_pc_address = nullptr; 669 // The constant pool recorded in the exit frame is not associated 670 // with the pc in this state (the return address into a C entry 671 // stub). ComputeCallerState will retrieve the constant pool 672 // together with the associated caller pc. 673 state->constant_pool_address = nullptr; 674 } 675 676 JSFunction* BuiltinExitFrame::function() const { 677 return JSFunction::cast(target_slot_object()); 678 } 679 680 Object* BuiltinExitFrame::receiver() const { return receiver_slot_object(); } 681 682 bool BuiltinExitFrame::IsConstructor() const { 683 return !new_target_slot_object()->IsUndefined(isolate()); 684 } 685 686 Object* BuiltinExitFrame::GetParameter(int i) const { 687 DCHECK(i >= 0 && i < ComputeParametersCount()); 688 int offset = 689 BuiltinExitFrameConstants::kFirstArgumentOffset + i * kPointerSize; 690 return Memory<Object*>(fp() + offset); 691 } 692 693 int BuiltinExitFrame::ComputeParametersCount() const { 694 Object* argc_slot = argc_slot_object(); 695 DCHECK(argc_slot->IsSmi()); 696 // Argc also counts the receiver, target, new target, and argc itself as args, 697 // therefore the real argument count is argc - 4. 698 int argc = Smi::ToInt(argc_slot) - 4; 699 DCHECK_GE(argc, 0); 700 return argc; 701 } 702 703 namespace { 704 void PrintIndex(StringStream* accumulator, StackFrame::PrintMode mode, 705 int index) { 706 accumulator->Add((mode == StackFrame::OVERVIEW) ? "%5d: " : "[%d]: ", index); 707 } 708 709 const char* StringForStackFrameType(StackFrame::Type type) { 710 switch (type) { 711 #define CASE(value, name) \ 712 case StackFrame::value: \ 713 return #name; 714 STACK_FRAME_TYPE_LIST(CASE) 715 #undef CASE 716 default: 717 UNREACHABLE(); 718 } 719 } 720 } // namespace 721 722 void StackFrame::Print(StringStream* accumulator, PrintMode mode, 723 int index) const { 724 DisallowHeapAllocation no_gc; 725 PrintIndex(accumulator, mode, index); 726 accumulator->Add(StringForStackFrameType(type())); 727 accumulator->Add(" [pc: %p]\n", reinterpret_cast<void*>(pc())); 728 } 729 730 void BuiltinExitFrame::Print(StringStream* accumulator, PrintMode mode, 731 int index) const { 732 DisallowHeapAllocation no_gc; 733 Object* receiver = this->receiver(); 734 JSFunction* function = this->function(); 735 736 accumulator->PrintSecurityTokenIfChanged(function); 737 PrintIndex(accumulator, mode, index); 738 accumulator->Add("builtin exit frame: "); 739 Code* code = nullptr; 740 if (IsConstructor()) accumulator->Add("new "); 741 accumulator->PrintFunction(function, receiver, &code); 742 743 accumulator->Add("(this=%o", receiver); 744 745 // Print the parameters. 746 int parameters_count = ComputeParametersCount(); 747 for (int i = 0; i < parameters_count; i++) { 748 accumulator->Add(",%o", GetParameter(i)); 749 } 750 751 accumulator->Add(")\n\n"); 752 } 753 754 Address StandardFrame::GetExpressionAddress(int n) const { 755 const int offset = StandardFrameConstants::kExpressionsOffset; 756 return fp() + offset - n * kPointerSize; 757 } 758 759 Address InterpretedFrame::GetExpressionAddress(int n) const { 760 const int offset = InterpreterFrameConstants::kExpressionsOffset; 761 return fp() + offset - n * kPointerSize; 762 } 763 764 Script* StandardFrame::script() const { 765 // This should only be called on frames which override this method. 766 DCHECK(false); 767 return nullptr; 768 } 769 770 Object* StandardFrame::receiver() const { 771 return ReadOnlyRoots(isolate()).undefined_value(); 772 } 773 774 Object* StandardFrame::context() const { 775 return ReadOnlyRoots(isolate()).undefined_value(); 776 } 777 778 int StandardFrame::position() const { 779 AbstractCode* code = AbstractCode::cast(LookupCode()); 780 int code_offset = static_cast<int>(pc() - code->InstructionStart()); 781 return code->SourcePosition(code_offset); 782 } 783 784 int StandardFrame::ComputeExpressionsCount() const { 785 Address base = GetExpressionAddress(0); 786 Address limit = sp() - kPointerSize; 787 DCHECK(base >= limit); // stack grows downwards 788 // Include register-allocated locals in number of expressions. 789 return static_cast<int>((base - limit) / kPointerSize); 790 } 791 792 Object* StandardFrame::GetParameter(int index) const { 793 // StandardFrame does not define any parameters. 794 UNREACHABLE(); 795 } 796 797 int StandardFrame::ComputeParametersCount() const { return 0; } 798 799 void StandardFrame::ComputeCallerState(State* state) const { 800 state->sp = caller_sp(); 801 state->fp = caller_fp(); 802 state->pc_address = ResolveReturnAddressLocation( 803 reinterpret_cast<Address*>(ComputePCAddress(fp()))); 804 state->callee_pc_address = pc_address(); 805 state->constant_pool_address = 806 reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp())); 807 } 808 809 810 bool StandardFrame::IsConstructor() const { return false; } 811 812 void StandardFrame::Summarize(std::vector<FrameSummary>* functions) const { 813 // This should only be called on frames which override this method. 814 UNREACHABLE(); 815 } 816 817 void StandardFrame::IterateCompiledFrame(RootVisitor* v) const { 818 // Make sure that we're not doing "safe" stack frame iteration. We cannot 819 // possibly find pointers in optimized frames in that state. 820 DCHECK(can_access_heap_objects()); 821 822 // Find the code and compute the safepoint information. 823 Address inner_pointer = pc(); 824 const wasm::WasmCode* wasm_code = 825 isolate()->wasm_engine()->code_manager()->LookupCode(inner_pointer); 826 SafepointEntry safepoint_entry; 827 uint32_t stack_slots; 828 Code* code = nullptr; 829 bool has_tagged_params = false; 830 if (wasm_code != nullptr) { 831 SafepointTable table(wasm_code->instruction_start(), 832 wasm_code->safepoint_table_offset(), 833 wasm_code->stack_slots()); 834 safepoint_entry = table.FindEntry(inner_pointer); 835 stack_slots = wasm_code->stack_slots(); 836 has_tagged_params = wasm_code->kind() != wasm::WasmCode::kFunction; 837 } else { 838 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry = 839 isolate()->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer); 840 if (!entry->safepoint_entry.is_valid()) { 841 entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer); 842 DCHECK(entry->safepoint_entry.is_valid()); 843 } else { 844 DCHECK(entry->safepoint_entry.Equals( 845 entry->code->GetSafepointEntry(inner_pointer))); 846 } 847 848 code = entry->code; 849 safepoint_entry = entry->safepoint_entry; 850 stack_slots = code->stack_slots(); 851 has_tagged_params = code->has_tagged_params(); 852 } 853 uint32_t slot_space = stack_slots * kPointerSize; 854 855 // Determine the fixed header and spill slot area size. 856 int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp; 857 intptr_t marker = 858 Memory<intptr_t>(fp() + CommonFrameConstants::kContextOrFrameTypeOffset); 859 if (StackFrame::IsTypeMarker(marker)) { 860 StackFrame::Type candidate = StackFrame::MarkerToType(marker); 861 switch (candidate) { 862 case ENTRY: 863 case CONSTRUCT_ENTRY: 864 case EXIT: 865 case BUILTIN_CONTINUATION: 866 case JAVA_SCRIPT_BUILTIN_CONTINUATION: 867 case JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH: 868 case BUILTIN_EXIT: 869 case ARGUMENTS_ADAPTOR: 870 case STUB: 871 case INTERNAL: 872 case CONSTRUCT: 873 case JS_TO_WASM: 874 case C_WASM_ENTRY: 875 frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp; 876 break; 877 case WASM_TO_JS: 878 case WASM_COMPILED: 879 case WASM_INTERPRETER_ENTRY: 880 case WASM_COMPILE_LAZY: 881 frame_header_size = WasmCompiledFrameConstants::kFixedFrameSizeFromFp; 882 break; 883 case OPTIMIZED: 884 case INTERPRETED: 885 case BUILTIN: 886 // These frame types have a context, but they are actually stored 887 // in the place on the stack that one finds the frame type. 888 UNREACHABLE(); 889 break; 890 case NATIVE: 891 case NONE: 892 case NUMBER_OF_TYPES: 893 case MANUAL: 894 UNREACHABLE(); 895 break; 896 } 897 } 898 slot_space -= 899 (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp); 900 901 Object** frame_header_base = &Memory<Object*>(fp() - frame_header_size); 902 Object** frame_header_limit = 903 &Memory<Object*>(fp() - StandardFrameConstants::kCPSlotSize); 904 Object** parameters_base = &Memory<Object*>(sp()); 905 Object** parameters_limit = frame_header_base - slot_space / kPointerSize; 906 907 // Visit the parameters that may be on top of the saved registers. 908 if (safepoint_entry.argument_count() > 0) { 909 v->VisitRootPointers(Root::kTop, nullptr, parameters_base, 910 parameters_base + safepoint_entry.argument_count()); 911 parameters_base += safepoint_entry.argument_count(); 912 } 913 914 // Skip saved double registers. 915 if (safepoint_entry.has_doubles()) { 916 // Number of doubles not known at snapshot time. 917 DCHECK(!isolate()->serializer_enabled()); 918 parameters_base += 919 RegisterConfiguration::Default()->num_allocatable_double_registers() * 920 kDoubleSize / kPointerSize; 921 } 922 923 // Visit the registers that contain pointers if any. 924 if (safepoint_entry.HasRegisters()) { 925 for (int i = kNumSafepointRegisters - 1; i >=0; i--) { 926 if (safepoint_entry.HasRegisterAt(i)) { 927 int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i); 928 v->VisitRootPointer(Root::kTop, nullptr, 929 parameters_base + reg_stack_index); 930 } 931 } 932 // Skip the words containing the register values. 933 parameters_base += kNumSafepointRegisters; 934 } 935 936 // We're done dealing with the register bits. 937 uint8_t* safepoint_bits = safepoint_entry.bits(); 938 safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2; 939 940 // Visit the rest of the parameters if they are tagged. 941 if (has_tagged_params) { 942 v->VisitRootPointers(Root::kTop, nullptr, parameters_base, 943 parameters_limit); 944 } 945 946 // Visit pointer spill slots and locals. 947 for (unsigned index = 0; index < stack_slots; index++) { 948 int byte_index = index >> kBitsPerByteLog2; 949 int bit_index = index & (kBitsPerByte - 1); 950 if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) { 951 v->VisitRootPointer(Root::kTop, nullptr, parameters_limit + index); 952 } 953 } 954 955 // For the off-heap code cases, we can skip this. 956 if (code != nullptr) { 957 // Visit the return address in the callee and incoming arguments. 958 IteratePc(v, pc_address(), constant_pool_address(), code); 959 } 960 961 // If this frame has JavaScript ABI, visit the context (in stub and JS 962 // frames) and the function (in JS frames). If it has WebAssembly ABI, visit 963 // the instance object. 964 v->VisitRootPointers(Root::kTop, nullptr, frame_header_base, 965 frame_header_limit); 966 } 967 968 void StubFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); } 969 970 Code* StubFrame::unchecked_code() const { 971 return isolate()->FindCodeObject(pc()); 972 } 973 974 975 Address StubFrame::GetCallerStackPointer() const { 976 return fp() + ExitFrameConstants::kCallerSPOffset; 977 } 978 979 980 int StubFrame::GetNumberOfIncomingArguments() const { 981 return 0; 982 } 983 984 int StubFrame::LookupExceptionHandlerInTable(int* stack_slots) { 985 Code* code = LookupCode(); 986 DCHECK(code->is_turbofanned()); 987 DCHECK_EQ(code->kind(), Code::BUILTIN); 988 HandlerTable table(code); 989 int pc_offset = static_cast<int>(pc() - code->InstructionStart()); 990 *stack_slots = code->stack_slots(); 991 return table.LookupReturn(pc_offset); 992 } 993 994 void OptimizedFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); } 995 996 void JavaScriptFrame::SetParameterValue(int index, Object* value) const { 997 Memory<Object*>(GetParameterSlot(index)) = value; 998 } 999 1000 1001 bool JavaScriptFrame::IsConstructor() const { 1002 Address fp = caller_fp(); 1003 if (has_adapted_arguments()) { 1004 // Skip the arguments adaptor frame and look at the real caller. 1005 fp = Memory<Address>(fp + StandardFrameConstants::kCallerFPOffset); 1006 } 1007 return IsConstructFrame(fp); 1008 } 1009 1010 1011 bool JavaScriptFrame::HasInlinedFrames() const { 1012 std::vector<SharedFunctionInfo*> functions; 1013 GetFunctions(&functions); 1014 return functions.size() > 1; 1015 } 1016 1017 1018 Code* JavaScriptFrame::unchecked_code() const { 1019 return function()->code(); 1020 } 1021 1022 1023 int JavaScriptFrame::GetNumberOfIncomingArguments() const { 1024 DCHECK(can_access_heap_objects() && 1025 isolate()->heap()->gc_state() == Heap::NOT_IN_GC); 1026 return function()->shared()->internal_formal_parameter_count(); 1027 } 1028 1029 int OptimizedFrame::GetNumberOfIncomingArguments() const { 1030 Code* code = LookupCode(); 1031 if (code->kind() == Code::BUILTIN) { 1032 return static_cast<int>( 1033 Memory<intptr_t>(fp() + OptimizedBuiltinFrameConstants::kArgCOffset)); 1034 } else { 1035 return JavaScriptFrame::GetNumberOfIncomingArguments(); 1036 } 1037 } 1038 1039 Address JavaScriptFrame::GetCallerStackPointer() const { 1040 return fp() + StandardFrameConstants::kCallerSPOffset; 1041 } 1042 1043 void JavaScriptFrame::GetFunctions( 1044 std::vector<SharedFunctionInfo*>* functions) const { 1045 DCHECK(functions->empty()); 1046 functions->push_back(function()->shared()); 1047 } 1048 1049 void JavaScriptFrame::GetFunctions( 1050 std::vector<Handle<SharedFunctionInfo>>* functions) const { 1051 DCHECK(functions->empty()); 1052 std::vector<SharedFunctionInfo*> raw_functions; 1053 GetFunctions(&raw_functions); 1054 for (const auto& raw_function : raw_functions) { 1055 functions->push_back( 1056 Handle<SharedFunctionInfo>(raw_function, function()->GetIsolate())); 1057 } 1058 } 1059 1060 void JavaScriptFrame::Summarize(std::vector<FrameSummary>* functions) const { 1061 DCHECK(functions->empty()); 1062 Code* code = LookupCode(); 1063 int offset = static_cast<int>(pc() - code->InstructionStart()); 1064 AbstractCode* abstract_code = AbstractCode::cast(code); 1065 FrameSummary::JavaScriptFrameSummary summary(isolate(), receiver(), 1066 function(), abstract_code, 1067 offset, IsConstructor()); 1068 functions->push_back(summary); 1069 } 1070 1071 JSFunction* JavaScriptFrame::function() const { 1072 return JSFunction::cast(function_slot_object()); 1073 } 1074 1075 Object* JavaScriptFrame::unchecked_function() const { 1076 // During deoptimization of an optimized function, we may have yet to 1077 // materialize some closures on the stack. The arguments marker object 1078 // marks this case. 1079 DCHECK(function_slot_object()->IsJSFunction() || 1080 ReadOnlyRoots(isolate()).arguments_marker() == function_slot_object()); 1081 return function_slot_object(); 1082 } 1083 1084 Object* JavaScriptFrame::receiver() const { return GetParameter(-1); } 1085 1086 Object* JavaScriptFrame::context() const { 1087 const int offset = StandardFrameConstants::kContextOffset; 1088 Object* maybe_result = Memory<Object*>(fp() + offset); 1089 DCHECK(!maybe_result->IsSmi()); 1090 return maybe_result; 1091 } 1092 1093 Script* JavaScriptFrame::script() const { 1094 return Script::cast(function()->shared()->script()); 1095 } 1096 1097 int JavaScriptFrame::LookupExceptionHandlerInTable( 1098 int* stack_depth, HandlerTable::CatchPrediction* prediction) { 1099 DCHECK_EQ(0, LookupCode()->handler_table_offset()); 1100 DCHECK(!LookupCode()->is_optimized_code()); 1101 return -1; 1102 } 1103 1104 void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function, 1105 AbstractCode* code, 1106 int code_offset, FILE* file, 1107 bool print_line_number) { 1108 PrintF(file, "%s", function->IsOptimized() ? "*" : "~"); 1109 function->PrintName(file); 1110 PrintF(file, "+%d", code_offset); 1111 if (print_line_number) { 1112 SharedFunctionInfo* shared = function->shared(); 1113 int source_pos = code->SourcePosition(code_offset); 1114 Object* maybe_script = shared->script(); 1115 if (maybe_script->IsScript()) { 1116 Script* script = Script::cast(maybe_script); 1117 int line = script->GetLineNumber(source_pos) + 1; 1118 Object* script_name_raw = script->name(); 1119 if (script_name_raw->IsString()) { 1120 String* script_name = String::cast(script->name()); 1121 std::unique_ptr<char[]> c_script_name = 1122 script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); 1123 PrintF(file, " at %s:%d", c_script_name.get(), line); 1124 } else { 1125 PrintF(file, " at <unknown>:%d", line); 1126 } 1127 } else { 1128 PrintF(file, " at <unknown>:<unknown>"); 1129 } 1130 } 1131 } 1132 1133 void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args, 1134 bool print_line_number) { 1135 // constructor calls 1136 DisallowHeapAllocation no_allocation; 1137 JavaScriptFrameIterator it(isolate); 1138 while (!it.done()) { 1139 if (it.frame()->is_java_script()) { 1140 JavaScriptFrame* frame = it.frame(); 1141 if (frame->IsConstructor()) PrintF(file, "new "); 1142 JSFunction* function = frame->function(); 1143 int code_offset = 0; 1144 if (frame->is_interpreted()) { 1145 InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame); 1146 code_offset = iframe->GetBytecodeOffset(); 1147 } else { 1148 Code* code = frame->unchecked_code(); 1149 code_offset = static_cast<int>(frame->pc() - code->InstructionStart()); 1150 } 1151 PrintFunctionAndOffset(function, function->abstract_code(), code_offset, 1152 file, print_line_number); 1153 if (print_args) { 1154 // function arguments 1155 // (we are intentionally only printing the actually 1156 // supplied parameters, not all parameters required) 1157 PrintF(file, "(this="); 1158 frame->receiver()->ShortPrint(file); 1159 const int length = frame->ComputeParametersCount(); 1160 for (int i = 0; i < length; i++) { 1161 PrintF(file, ", "); 1162 frame->GetParameter(i)->ShortPrint(file); 1163 } 1164 PrintF(file, ")"); 1165 } 1166 break; 1167 } 1168 it.Advance(); 1169 } 1170 } 1171 1172 void JavaScriptFrame::CollectFunctionAndOffsetForICStats(JSFunction* function, 1173 AbstractCode* code, 1174 int code_offset) { 1175 auto ic_stats = ICStats::instance(); 1176 ICInfo& ic_info = ic_stats->Current(); 1177 SharedFunctionInfo* shared = function->shared(); 1178 1179 ic_info.function_name = ic_stats->GetOrCacheFunctionName(function); 1180 ic_info.script_offset = code_offset; 1181 1182 int source_pos = code->SourcePosition(code_offset); 1183 Object* maybe_script = shared->script(); 1184 if (maybe_script->IsScript()) { 1185 Script* script = Script::cast(maybe_script); 1186 ic_info.line_num = script->GetLineNumber(source_pos) + 1; 1187 ic_info.script_name = ic_stats->GetOrCacheScriptName(script); 1188 } 1189 } 1190 1191 void JavaScriptFrame::CollectTopFrameForICStats(Isolate* isolate) { 1192 // constructor calls 1193 DisallowHeapAllocation no_allocation; 1194 JavaScriptFrameIterator it(isolate); 1195 ICInfo& ic_info = ICStats::instance()->Current(); 1196 while (!it.done()) { 1197 if (it.frame()->is_java_script()) { 1198 JavaScriptFrame* frame = it.frame(); 1199 if (frame->IsConstructor()) ic_info.is_constructor = true; 1200 JSFunction* function = frame->function(); 1201 int code_offset = 0; 1202 if (frame->is_interpreted()) { 1203 InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame); 1204 code_offset = iframe->GetBytecodeOffset(); 1205 } else { 1206 Code* code = frame->unchecked_code(); 1207 code_offset = static_cast<int>(frame->pc() - code->InstructionStart()); 1208 } 1209 CollectFunctionAndOffsetForICStats(function, function->abstract_code(), 1210 code_offset); 1211 return; 1212 } 1213 it.Advance(); 1214 } 1215 } 1216 1217 Object* JavaScriptFrame::GetParameter(int index) const { 1218 return Memory<Object*>(GetParameterSlot(index)); 1219 } 1220 1221 int JavaScriptFrame::ComputeParametersCount() const { 1222 return GetNumberOfIncomingArguments(); 1223 } 1224 1225 int JavaScriptBuiltinContinuationFrame::ComputeParametersCount() const { 1226 // Assert that the first allocatable register is also the argument count 1227 // register. 1228 DCHECK_EQ(RegisterConfiguration::Default()->GetAllocatableGeneralCode(0), 1229 kJavaScriptCallArgCountRegister.code()); 1230 Object* argc_object = 1231 Memory<Object*>(fp() + BuiltinContinuationFrameConstants::kArgCOffset); 1232 return Smi::ToInt(argc_object); 1233 } 1234 1235 intptr_t JavaScriptBuiltinContinuationFrame::GetSPToFPDelta() const { 1236 Address height_slot = 1237 fp() + BuiltinContinuationFrameConstants::kFrameSPtoFPDeltaAtDeoptimize; 1238 intptr_t height = Smi::ToInt(*reinterpret_cast<Smi**>(height_slot)); 1239 return height; 1240 } 1241 1242 Object* JavaScriptBuiltinContinuationFrame::context() const { 1243 return Memory<Object*>( 1244 fp() + BuiltinContinuationFrameConstants::kBuiltinContextOffset); 1245 } 1246 1247 void JavaScriptBuiltinContinuationWithCatchFrame::SetException( 1248 Object* exception) { 1249 Address exception_argument_slot = 1250 fp() + JavaScriptFrameConstants::kLastParameterOffset + 1251 kPointerSize; // Skip over return value slot. 1252 1253 // Only allow setting exception if previous value was the hole. 1254 CHECK_EQ(ReadOnlyRoots(isolate()).the_hole_value(), 1255 Memory<Object*>(exception_argument_slot)); 1256 Memory<Object*>(exception_argument_slot) = exception; 1257 } 1258 1259 FrameSummary::JavaScriptFrameSummary::JavaScriptFrameSummary( 1260 Isolate* isolate, Object* receiver, JSFunction* function, 1261 AbstractCode* abstract_code, int code_offset, bool is_constructor) 1262 : FrameSummaryBase(isolate, FrameSummary::JAVA_SCRIPT), 1263 receiver_(receiver, isolate), 1264 function_(function, isolate), 1265 abstract_code_(abstract_code, isolate), 1266 code_offset_(code_offset), 1267 is_constructor_(is_constructor) { 1268 DCHECK(abstract_code->IsBytecodeArray() || 1269 Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION); 1270 } 1271 1272 bool FrameSummary::JavaScriptFrameSummary::is_subject_to_debugging() const { 1273 return function()->shared()->IsSubjectToDebugging(); 1274 } 1275 1276 int FrameSummary::JavaScriptFrameSummary::SourcePosition() const { 1277 return abstract_code()->SourcePosition(code_offset()); 1278 } 1279 1280 int FrameSummary::JavaScriptFrameSummary::SourceStatementPosition() const { 1281 return abstract_code()->SourceStatementPosition(code_offset()); 1282 } 1283 1284 Handle<Object> FrameSummary::JavaScriptFrameSummary::script() const { 1285 return handle(function_->shared()->script(), isolate()); 1286 } 1287 1288 Handle<String> FrameSummary::JavaScriptFrameSummary::FunctionName() const { 1289 return JSFunction::GetDebugName(function_); 1290 } 1291 1292 Handle<Context> FrameSummary::JavaScriptFrameSummary::native_context() const { 1293 return handle(function_->context()->native_context(), isolate()); 1294 } 1295 1296 FrameSummary::WasmFrameSummary::WasmFrameSummary( 1297 Isolate* isolate, FrameSummary::Kind kind, 1298 Handle<WasmInstanceObject> instance, bool at_to_number_conversion) 1299 : FrameSummaryBase(isolate, kind), 1300 wasm_instance_(instance), 1301 at_to_number_conversion_(at_to_number_conversion) {} 1302 1303 Handle<Object> FrameSummary::WasmFrameSummary::receiver() const { 1304 return wasm_instance_->GetIsolate()->global_proxy(); 1305 } 1306 1307 #define WASM_SUMMARY_DISPATCH(type, name) \ 1308 type FrameSummary::WasmFrameSummary::name() const { \ 1309 DCHECK(kind() == Kind::WASM_COMPILED || kind() == Kind::WASM_INTERPRETED); \ 1310 return kind() == Kind::WASM_COMPILED \ 1311 ? static_cast<const WasmCompiledFrameSummary*>(this)->name() \ 1312 : static_cast<const WasmInterpretedFrameSummary*>(this) \ 1313 ->name(); \ 1314 } 1315 1316 WASM_SUMMARY_DISPATCH(uint32_t, function_index) 1317 WASM_SUMMARY_DISPATCH(int, byte_offset) 1318 1319 #undef WASM_SUMMARY_DISPATCH 1320 1321 int FrameSummary::WasmFrameSummary::SourcePosition() const { 1322 Handle<WasmModuleObject> module_object(wasm_instance()->module_object(), 1323 isolate()); 1324 return WasmModuleObject::GetSourcePosition(module_object, function_index(), 1325 byte_offset(), 1326 at_to_number_conversion()); 1327 } 1328 1329 Handle<Script> FrameSummary::WasmFrameSummary::script() const { 1330 return handle(wasm_instance()->module_object()->script(), 1331 wasm_instance()->GetIsolate()); 1332 } 1333 1334 Handle<String> FrameSummary::WasmFrameSummary::FunctionName() const { 1335 Handle<WasmModuleObject> module_object(wasm_instance()->module_object(), 1336 isolate()); 1337 return WasmModuleObject::GetFunctionName(isolate(), module_object, 1338 function_index()); 1339 } 1340 1341 Handle<Context> FrameSummary::WasmFrameSummary::native_context() const { 1342 return handle(wasm_instance()->native_context(), isolate()); 1343 } 1344 1345 FrameSummary::WasmCompiledFrameSummary::WasmCompiledFrameSummary( 1346 Isolate* isolate, Handle<WasmInstanceObject> instance, wasm::WasmCode* code, 1347 int code_offset, bool at_to_number_conversion) 1348 : WasmFrameSummary(isolate, WASM_COMPILED, instance, 1349 at_to_number_conversion), 1350 code_(code), 1351 code_offset_(code_offset) {} 1352 1353 uint32_t FrameSummary::WasmCompiledFrameSummary::function_index() const { 1354 return code()->index(); 1355 } 1356 1357 int FrameSummary::WasmCompiledFrameSummary::GetWasmSourcePosition( 1358 const wasm::WasmCode* code, int offset) { 1359 int position = 0; 1360 // Subtract one because the current PC is one instruction after the call site. 1361 offset--; 1362 for (SourcePositionTableIterator iterator(code->source_positions()); 1363 !iterator.done() && iterator.code_offset() <= offset; 1364 iterator.Advance()) { 1365 position = iterator.source_position().ScriptOffset(); 1366 } 1367 return position; 1368 } 1369 1370 int FrameSummary::WasmCompiledFrameSummary::byte_offset() const { 1371 return GetWasmSourcePosition(code_, code_offset()); 1372 } 1373 1374 FrameSummary::WasmInterpretedFrameSummary::WasmInterpretedFrameSummary( 1375 Isolate* isolate, Handle<WasmInstanceObject> instance, 1376 uint32_t function_index, int byte_offset) 1377 : WasmFrameSummary(isolate, WASM_INTERPRETED, instance, false), 1378 function_index_(function_index), 1379 byte_offset_(byte_offset) {} 1380 1381 FrameSummary::~FrameSummary() { 1382 #define FRAME_SUMMARY_DESTR(kind, type, field, desc) \ 1383 case kind: \ 1384 field.~type(); \ 1385 break; 1386 switch (base_.kind()) { 1387 FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_DESTR) 1388 default: 1389 UNREACHABLE(); 1390 } 1391 #undef FRAME_SUMMARY_DESTR 1392 } 1393 1394 FrameSummary FrameSummary::GetTop(const StandardFrame* frame) { 1395 std::vector<FrameSummary> frames; 1396 frame->Summarize(&frames); 1397 DCHECK_LT(0, frames.size()); 1398 return frames.back(); 1399 } 1400 1401 FrameSummary FrameSummary::GetBottom(const StandardFrame* frame) { 1402 return Get(frame, 0); 1403 } 1404 1405 FrameSummary FrameSummary::GetSingle(const StandardFrame* frame) { 1406 std::vector<FrameSummary> frames; 1407 frame->Summarize(&frames); 1408 DCHECK_EQ(1, frames.size()); 1409 return frames.front(); 1410 } 1411 1412 FrameSummary FrameSummary::Get(const StandardFrame* frame, int index) { 1413 DCHECK_LE(0, index); 1414 std::vector<FrameSummary> frames; 1415 frame->Summarize(&frames); 1416 DCHECK_GT(frames.size(), index); 1417 return frames[index]; 1418 } 1419 1420 #define FRAME_SUMMARY_DISPATCH(ret, name) \ 1421 ret FrameSummary::name() const { \ 1422 switch (base_.kind()) { \ 1423 case JAVA_SCRIPT: \ 1424 return java_script_summary_.name(); \ 1425 case WASM_COMPILED: \ 1426 return wasm_compiled_summary_.name(); \ 1427 case WASM_INTERPRETED: \ 1428 return wasm_interpreted_summary_.name(); \ 1429 default: \ 1430 UNREACHABLE(); \ 1431 return ret{}; \ 1432 } \ 1433 } 1434 1435 FRAME_SUMMARY_DISPATCH(Handle<Object>, receiver) 1436 FRAME_SUMMARY_DISPATCH(int, code_offset) 1437 FRAME_SUMMARY_DISPATCH(bool, is_constructor) 1438 FRAME_SUMMARY_DISPATCH(bool, is_subject_to_debugging) 1439 FRAME_SUMMARY_DISPATCH(Handle<Object>, script) 1440 FRAME_SUMMARY_DISPATCH(int, SourcePosition) 1441 FRAME_SUMMARY_DISPATCH(int, SourceStatementPosition) 1442 FRAME_SUMMARY_DISPATCH(Handle<String>, FunctionName) 1443 FRAME_SUMMARY_DISPATCH(Handle<Context>, native_context) 1444 1445 #undef FRAME_SUMMARY_DISPATCH 1446 1447 void OptimizedFrame::Summarize(std::vector<FrameSummary>* frames) const { 1448 DCHECK(frames->empty()); 1449 DCHECK(is_optimized()); 1450 1451 // Delegate to JS frame in absence of turbofan deoptimization. 1452 // TODO(turbofan): Revisit once we support deoptimization across the board. 1453 Code* code = LookupCode(); 1454 if (code->kind() == Code::BUILTIN) { 1455 return JavaScriptFrame::Summarize(frames); 1456 } 1457 1458 int deopt_index = Safepoint::kNoDeoptimizationIndex; 1459 DeoptimizationData* const data = GetDeoptimizationData(&deopt_index); 1460 if (deopt_index == Safepoint::kNoDeoptimizationIndex) { 1461 CHECK_NULL(data); 1462 FATAL("Missing deoptimization information for OptimizedFrame::Summarize."); 1463 } 1464 1465 // Prepare iteration over translation. Note that the below iteration might 1466 // materialize objects without storing them back to the Isolate, this will 1467 // lead to objects being re-materialized again for each summary. 1468 TranslatedState translated(this); 1469 translated.Prepare(fp()); 1470 1471 // We create the summary in reverse order because the frames 1472 // in the deoptimization translation are ordered bottom-to-top. 1473 bool is_constructor = IsConstructor(); 1474 for (auto it = translated.begin(); it != translated.end(); it++) { 1475 if (it->kind() == TranslatedFrame::kInterpretedFunction || 1476 it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation || 1477 it->kind() == 1478 TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) { 1479 Handle<SharedFunctionInfo> shared_info = it->shared_info(); 1480 1481 // The translation commands are ordered and the function is always 1482 // at the first position, and the receiver is next. 1483 TranslatedFrame::iterator translated_values = it->begin(); 1484 1485 // Get or materialize the correct function in the optimized frame. 1486 Handle<JSFunction> function = 1487 Handle<JSFunction>::cast(translated_values->GetValue()); 1488 translated_values++; 1489 1490 // Get or materialize the correct receiver in the optimized frame. 1491 Handle<Object> receiver = translated_values->GetValue(); 1492 translated_values++; 1493 1494 // Determine the underlying code object and the position within it from 1495 // the translation corresponding to the frame type in question. 1496 Handle<AbstractCode> abstract_code; 1497 unsigned code_offset; 1498 if (it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation || 1499 it->kind() == 1500 TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) { 1501 code_offset = 0; 1502 abstract_code = 1503 handle(AbstractCode::cast(isolate()->builtins()->builtin( 1504 Builtins::GetBuiltinFromBailoutId(it->node_id()))), 1505 isolate()); 1506 } else { 1507 DCHECK_EQ(it->kind(), TranslatedFrame::kInterpretedFunction); 1508 code_offset = it->node_id().ToInt(); // Points to current bytecode. 1509 abstract_code = handle(shared_info->abstract_code(), isolate()); 1510 } 1511 1512 // Append full summary of the encountered JS frame. 1513 FrameSummary::JavaScriptFrameSummary summary(isolate(), *receiver, 1514 *function, *abstract_code, 1515 code_offset, is_constructor); 1516 frames->push_back(summary); 1517 is_constructor = false; 1518 } else if (it->kind() == TranslatedFrame::kConstructStub) { 1519 // The next encountered JS frame will be marked as a constructor call. 1520 DCHECK(!is_constructor); 1521 is_constructor = true; 1522 } 1523 } 1524 } 1525 1526 1527 int OptimizedFrame::LookupExceptionHandlerInTable( 1528 int* stack_slots, HandlerTable::CatchPrediction* prediction) { 1529 // We cannot perform exception prediction on optimized code. Instead, we need 1530 // to use FrameSummary to find the corresponding code offset in unoptimized 1531 // code to perform prediction there. 1532 DCHECK_NULL(prediction); 1533 Code* code = LookupCode(); 1534 HandlerTable table(code); 1535 int pc_offset = static_cast<int>(pc() - code->InstructionStart()); 1536 if (stack_slots) *stack_slots = code->stack_slots(); 1537 1538 // When the return pc has been replaced by a trampoline there won't be 1539 // a handler for this trampoline. Thus we need to use the return pc that 1540 // _used to be_ on the stack to get the right ExceptionHandler. 1541 if (code->kind() == Code::OPTIMIZED_FUNCTION && 1542 code->marked_for_deoptimization()) { 1543 SafepointTable safepoints(code); 1544 pc_offset = safepoints.find_return_pc(pc_offset); 1545 } 1546 return table.LookupReturn(pc_offset); 1547 } 1548 1549 DeoptimizationData* OptimizedFrame::GetDeoptimizationData( 1550 int* deopt_index) const { 1551 DCHECK(is_optimized()); 1552 1553 JSFunction* opt_function = function(); 1554 Code* code = opt_function->code(); 1555 1556 // The code object may have been replaced by lazy deoptimization. Fall 1557 // back to a slow search in this case to find the original optimized 1558 // code object. 1559 if (!code->contains(pc())) { 1560 code = isolate()->heap()->GcSafeFindCodeForInnerPointer(pc()); 1561 } 1562 DCHECK_NOT_NULL(code); 1563 DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION); 1564 1565 SafepointEntry safepoint_entry = code->GetSafepointEntry(pc()); 1566 *deopt_index = safepoint_entry.deoptimization_index(); 1567 if (*deopt_index != Safepoint::kNoDeoptimizationIndex) { 1568 return DeoptimizationData::cast(code->deoptimization_data()); 1569 } 1570 return nullptr; 1571 } 1572 1573 Object* OptimizedFrame::receiver() const { 1574 Code* code = LookupCode(); 1575 if (code->kind() == Code::BUILTIN) { 1576 Address argc_ptr = fp() + OptimizedBuiltinFrameConstants::kArgCOffset; 1577 intptr_t argc = *reinterpret_cast<intptr_t*>(argc_ptr); 1578 intptr_t args_size = 1579 (StandardFrameConstants::kFixedSlotCountAboveFp + argc) * kPointerSize; 1580 Address receiver_ptr = fp() + args_size; 1581 return *reinterpret_cast<Object**>(receiver_ptr); 1582 } else { 1583 return JavaScriptFrame::receiver(); 1584 } 1585 } 1586 1587 void OptimizedFrame::GetFunctions( 1588 std::vector<SharedFunctionInfo*>* functions) const { 1589 DCHECK(functions->empty()); 1590 DCHECK(is_optimized()); 1591 1592 // Delegate to JS frame in absence of turbofan deoptimization. 1593 // TODO(turbofan): Revisit once we support deoptimization across the board. 1594 Code* code = LookupCode(); 1595 if (code->kind() == Code::BUILTIN) { 1596 return JavaScriptFrame::GetFunctions(functions); 1597 } 1598 1599 DisallowHeapAllocation no_gc; 1600 int deopt_index = Safepoint::kNoDeoptimizationIndex; 1601 DeoptimizationData* const data = GetDeoptimizationData(&deopt_index); 1602 DCHECK_NOT_NULL(data); 1603 DCHECK_NE(Safepoint::kNoDeoptimizationIndex, deopt_index); 1604 FixedArray* const literal_array = data->LiteralArray(); 1605 1606 TranslationIterator it(data->TranslationByteArray(), 1607 data->TranslationIndex(deopt_index)->value()); 1608 Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); 1609 DCHECK_EQ(Translation::BEGIN, opcode); 1610 it.Next(); // Skip frame count. 1611 int jsframe_count = it.Next(); 1612 it.Next(); // Skip update feedback count. 1613 1614 // We insert the frames in reverse order because the frames 1615 // in the deoptimization translation are ordered bottom-to-top. 1616 while (jsframe_count != 0) { 1617 opcode = static_cast<Translation::Opcode>(it.Next()); 1618 if (opcode == Translation::INTERPRETED_FRAME || 1619 opcode == Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME || 1620 opcode == 1621 Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME) { 1622 it.Next(); // Skip bailout id. 1623 jsframe_count--; 1624 1625 // The second operand of the frame points to the function. 1626 Object* shared = literal_array->get(it.Next()); 1627 functions->push_back(SharedFunctionInfo::cast(shared)); 1628 1629 // Skip over remaining operands to advance to the next opcode. 1630 it.Skip(Translation::NumberOfOperandsFor(opcode) - 2); 1631 } else { 1632 // Skip over operands to advance to the next opcode. 1633 it.Skip(Translation::NumberOfOperandsFor(opcode)); 1634 } 1635 } 1636 } 1637 1638 1639 int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) { 1640 return StandardFrameConstants::kCallerSPOffset - 1641 ((slot_index + 1) * kPointerSize); 1642 } 1643 1644 1645 Object* OptimizedFrame::StackSlotAt(int index) const { 1646 return Memory<Object*>(fp() + StackSlotOffsetRelativeToFp(index)); 1647 } 1648 1649 int InterpretedFrame::position() const { 1650 AbstractCode* code = AbstractCode::cast(GetBytecodeArray()); 1651 int code_offset = GetBytecodeOffset(); 1652 return code->SourcePosition(code_offset); 1653 } 1654 1655 int InterpretedFrame::LookupExceptionHandlerInTable( 1656 int* context_register, HandlerTable::CatchPrediction* prediction) { 1657 HandlerTable table(function()->shared()->GetBytecodeArray()); 1658 return table.LookupRange(GetBytecodeOffset(), context_register, prediction); 1659 } 1660 1661 int InterpretedFrame::GetBytecodeOffset() const { 1662 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex; 1663 DCHECK_EQ( 1664 InterpreterFrameConstants::kBytecodeOffsetFromFp, 1665 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize); 1666 int raw_offset = Smi::ToInt(GetExpression(index)); 1667 return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag; 1668 } 1669 1670 int InterpretedFrame::GetBytecodeOffset(Address fp) { 1671 const int offset = InterpreterFrameConstants::kExpressionsOffset; 1672 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex; 1673 DCHECK_EQ( 1674 InterpreterFrameConstants::kBytecodeOffsetFromFp, 1675 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize); 1676 Address expression_offset = fp + offset - index * kPointerSize; 1677 int raw_offset = Smi::ToInt(Memory<Object*>(expression_offset)); 1678 return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag; 1679 } 1680 1681 void InterpretedFrame::PatchBytecodeOffset(int new_offset) { 1682 const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex; 1683 DCHECK_EQ( 1684 InterpreterFrameConstants::kBytecodeOffsetFromFp, 1685 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize); 1686 int raw_offset = new_offset + BytecodeArray::kHeaderSize - kHeapObjectTag; 1687 SetExpression(index, Smi::FromInt(raw_offset)); 1688 } 1689 1690 BytecodeArray* InterpretedFrame::GetBytecodeArray() const { 1691 const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex; 1692 DCHECK_EQ( 1693 InterpreterFrameConstants::kBytecodeArrayFromFp, 1694 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize); 1695 return BytecodeArray::cast(GetExpression(index)); 1696 } 1697 1698 void InterpretedFrame::PatchBytecodeArray(BytecodeArray* bytecode_array) { 1699 const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex; 1700 DCHECK_EQ( 1701 InterpreterFrameConstants::kBytecodeArrayFromFp, 1702 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize); 1703 SetExpression(index, bytecode_array); 1704 } 1705 1706 Object* InterpretedFrame::ReadInterpreterRegister(int register_index) const { 1707 const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex; 1708 DCHECK_EQ( 1709 InterpreterFrameConstants::kRegisterFileFromFp, 1710 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize); 1711 return GetExpression(index + register_index); 1712 } 1713 1714 void InterpretedFrame::WriteInterpreterRegister(int register_index, 1715 Object* value) { 1716 const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex; 1717 DCHECK_EQ( 1718 InterpreterFrameConstants::kRegisterFileFromFp, 1719 InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize); 1720 return SetExpression(index + register_index, value); 1721 } 1722 1723 void InterpretedFrame::Summarize(std::vector<FrameSummary>* functions) const { 1724 DCHECK(functions->empty()); 1725 AbstractCode* abstract_code = 1726 AbstractCode::cast(function()->shared()->GetBytecodeArray()); 1727 FrameSummary::JavaScriptFrameSummary summary( 1728 isolate(), receiver(), function(), abstract_code, GetBytecodeOffset(), 1729 IsConstructor()); 1730 functions->push_back(summary); 1731 } 1732 1733 int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const { 1734 return Smi::ToInt(GetExpression(0)); 1735 } 1736 1737 Code* ArgumentsAdaptorFrame::unchecked_code() const { 1738 return isolate()->builtins()->builtin( 1739 Builtins::kArgumentsAdaptorTrampoline); 1740 } 1741 1742 int BuiltinFrame::GetNumberOfIncomingArguments() const { 1743 return Smi::ToInt(GetExpression(0)); 1744 } 1745 1746 void BuiltinFrame::PrintFrameKind(StringStream* accumulator) const { 1747 accumulator->Add("builtin frame: "); 1748 } 1749 1750 Address InternalFrame::GetCallerStackPointer() const { 1751 // Internal frames have no arguments. The stack pointer of the 1752 // caller is at a fixed offset from the frame pointer. 1753 return fp() + StandardFrameConstants::kCallerSPOffset; 1754 } 1755 1756 Code* InternalFrame::unchecked_code() const { UNREACHABLE(); } 1757 1758 void WasmCompiledFrame::Print(StringStream* accumulator, PrintMode mode, 1759 int index) const { 1760 PrintIndex(accumulator, mode, index); 1761 accumulator->Add("WASM ["); 1762 accumulator->PrintName(script()->name()); 1763 Address instruction_start = isolate() 1764 ->wasm_engine() 1765 ->code_manager() 1766 ->LookupCode(pc()) 1767 ->instruction_start(); 1768 Vector<const uint8_t> raw_func_name = 1769 module_object()->GetRawFunctionName(function_index()); 1770 const int kMaxPrintedFunctionName = 64; 1771 char func_name[kMaxPrintedFunctionName + 1]; 1772 int func_name_len = std::min(kMaxPrintedFunctionName, raw_func_name.length()); 1773 memcpy(func_name, raw_func_name.start(), func_name_len); 1774 func_name[func_name_len] = '\0'; 1775 int pos = position(); 1776 const wasm::WasmModule* module = wasm_instance()->module_object()->module(); 1777 int func_index = function_index(); 1778 int func_code_offset = module->functions[func_index].code.offset(); 1779 accumulator->Add("], function #%u ('%s'), pc=%p (+0x%x), pos=%d (+%d)\n", 1780 func_index, func_name, reinterpret_cast<void*>(pc()), 1781 static_cast<int>(pc() - instruction_start), pos, 1782 pos - func_code_offset); 1783 if (mode != OVERVIEW) accumulator->Add("\n"); 1784 } 1785 1786 Code* WasmCompiledFrame::unchecked_code() const { 1787 return isolate()->FindCodeObject(pc()); 1788 } 1789 1790 void WasmCompiledFrame::Iterate(RootVisitor* v) const { 1791 IterateCompiledFrame(v); 1792 } 1793 1794 Address WasmCompiledFrame::GetCallerStackPointer() const { 1795 return fp() + ExitFrameConstants::kCallerSPOffset; 1796 } 1797 1798 wasm::WasmCode* WasmCompiledFrame::wasm_code() const { 1799 return isolate()->wasm_engine()->code_manager()->LookupCode(pc()); 1800 } 1801 1802 WasmInstanceObject* WasmCompiledFrame::wasm_instance() const { 1803 const int offset = WasmCompiledFrameConstants::kWasmInstanceOffset; 1804 Object* instance = Memory<Object*>(fp() + offset); 1805 return WasmInstanceObject::cast(instance); 1806 } 1807 1808 WasmModuleObject* WasmCompiledFrame::module_object() const { 1809 return wasm_instance()->module_object(); 1810 } 1811 1812 uint32_t WasmCompiledFrame::function_index() const { 1813 return FrameSummary::GetSingle(this).AsWasmCompiled().function_index(); 1814 } 1815 1816 Script* WasmCompiledFrame::script() const { return module_object()->script(); } 1817 1818 int WasmCompiledFrame::position() const { 1819 return FrameSummary::GetSingle(this).SourcePosition(); 1820 } 1821 1822 void WasmCompiledFrame::Summarize(std::vector<FrameSummary>* functions) const { 1823 DCHECK(functions->empty()); 1824 wasm::WasmCode* code = wasm_code(); 1825 int offset = static_cast<int>(pc() - code->instruction_start()); 1826 Handle<WasmInstanceObject> instance(wasm_instance(), isolate()); 1827 FrameSummary::WasmCompiledFrameSummary summary( 1828 isolate(), instance, code, offset, at_to_number_conversion()); 1829 functions->push_back(summary); 1830 } 1831 1832 bool WasmCompiledFrame::at_to_number_conversion() const { 1833 // Check whether our callee is a WASM_TO_JS frame, and this frame is at the 1834 // ToNumber conversion call. 1835 wasm::WasmCode* code = 1836 callee_pc() != kNullAddress 1837 ? isolate()->wasm_engine()->code_manager()->LookupCode(callee_pc()) 1838 : nullptr; 1839 if (!code || code->kind() != wasm::WasmCode::kWasmToJsWrapper) return false; 1840 int offset = static_cast<int>(callee_pc() - code->instruction_start()); 1841 int pos = FrameSummary::WasmCompiledFrameSummary::GetWasmSourcePosition( 1842 code, offset); 1843 DCHECK(pos == 0 || pos == 1); 1844 // The imported call has position 0, ToNumber has position 1. 1845 return !!pos; 1846 } 1847 1848 int WasmCompiledFrame::LookupExceptionHandlerInTable(int* stack_slots) { 1849 DCHECK_NOT_NULL(stack_slots); 1850 wasm::WasmCode* code = 1851 isolate()->wasm_engine()->code_manager()->LookupCode(pc()); 1852 if (!code->IsAnonymous() && code->handler_table_offset() > 0) { 1853 HandlerTable table(code->instruction_start(), code->handler_table_offset()); 1854 int pc_offset = static_cast<int>(pc() - code->instruction_start()); 1855 *stack_slots = static_cast<int>(code->stack_slots()); 1856 return table.LookupReturn(pc_offset); 1857 } 1858 return -1; 1859 } 1860 1861 void WasmInterpreterEntryFrame::Iterate(RootVisitor* v) const { 1862 IterateCompiledFrame(v); 1863 } 1864 1865 void WasmInterpreterEntryFrame::Print(StringStream* accumulator, PrintMode mode, 1866 int index) const { 1867 PrintIndex(accumulator, mode, index); 1868 accumulator->Add("WASM INTERPRETER ENTRY ["); 1869 Script* script = this->script(); 1870 accumulator->PrintName(script->name()); 1871 accumulator->Add("]"); 1872 if (mode != OVERVIEW) accumulator->Add("\n"); 1873 } 1874 1875 void WasmInterpreterEntryFrame::Summarize( 1876 std::vector<FrameSummary>* functions) const { 1877 Handle<WasmInstanceObject> instance(wasm_instance(), isolate()); 1878 std::vector<std::pair<uint32_t, int>> interpreted_stack = 1879 instance->debug_info()->GetInterpretedStack(fp()); 1880 1881 for (auto& e : interpreted_stack) { 1882 FrameSummary::WasmInterpretedFrameSummary summary(isolate(), instance, 1883 e.first, e.second); 1884 functions->push_back(summary); 1885 } 1886 } 1887 1888 Code* WasmInterpreterEntryFrame::unchecked_code() const { UNREACHABLE(); } 1889 1890 WasmInstanceObject* WasmInterpreterEntryFrame::wasm_instance() const { 1891 const int offset = WasmCompiledFrameConstants::kWasmInstanceOffset; 1892 Object* instance = Memory<Object*>(fp() + offset); 1893 return WasmInstanceObject::cast(instance); 1894 } 1895 1896 WasmDebugInfo* WasmInterpreterEntryFrame::debug_info() const { 1897 return wasm_instance()->debug_info(); 1898 } 1899 1900 WasmModuleObject* WasmInterpreterEntryFrame::module_object() const { 1901 return wasm_instance()->module_object(); 1902 } 1903 1904 Script* WasmInterpreterEntryFrame::script() const { 1905 return module_object()->script(); 1906 } 1907 1908 int WasmInterpreterEntryFrame::position() const { 1909 return FrameSummary::GetBottom(this).AsWasmInterpreted().SourcePosition(); 1910 } 1911 1912 Object* WasmInterpreterEntryFrame::context() const { 1913 return wasm_instance()->native_context(); 1914 } 1915 1916 Address WasmInterpreterEntryFrame::GetCallerStackPointer() const { 1917 return fp() + ExitFrameConstants::kCallerSPOffset; 1918 } 1919 1920 WasmInstanceObject* WasmCompileLazyFrame::wasm_instance() const { 1921 return WasmInstanceObject::cast(*wasm_instance_slot()); 1922 } 1923 1924 Object** WasmCompileLazyFrame::wasm_instance_slot() const { 1925 const int offset = WasmCompileLazyFrameConstants::kWasmInstanceOffset; 1926 return &Memory<Object*>(fp() + offset); 1927 } 1928 1929 void WasmCompileLazyFrame::Iterate(RootVisitor* v) const { 1930 const int header_size = WasmCompileLazyFrameConstants::kFixedFrameSizeFromFp; 1931 Object** base = &Memory<Object*>(sp()); 1932 Object** limit = &Memory<Object*>(fp() - header_size); 1933 v->VisitRootPointers(Root::kTop, nullptr, base, limit); 1934 v->VisitRootPointer(Root::kTop, nullptr, wasm_instance_slot()); 1935 } 1936 1937 Address WasmCompileLazyFrame::GetCallerStackPointer() const { 1938 return fp() + WasmCompileLazyFrameConstants::kCallerSPOffset; 1939 } 1940 1941 namespace { 1942 1943 1944 void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared, 1945 Code* code) { 1946 if (FLAG_max_stack_trace_source_length != 0 && code != nullptr) { 1947 std::ostringstream os; 1948 os << "--------- s o u r c e c o d e ---------\n" 1949 << SourceCodeOf(shared, FLAG_max_stack_trace_source_length) 1950 << "\n-----------------------------------------\n"; 1951 accumulator->Add(os.str().c_str()); 1952 } 1953 } 1954 1955 1956 } // namespace 1957 1958 1959 void JavaScriptFrame::Print(StringStream* accumulator, 1960 PrintMode mode, 1961 int index) const { 1962 DisallowHeapAllocation no_gc; 1963 Object* receiver = this->receiver(); 1964 JSFunction* function = this->function(); 1965 1966 accumulator->PrintSecurityTokenIfChanged(function); 1967 PrintIndex(accumulator, mode, index); 1968 PrintFrameKind(accumulator); 1969 Code* code = nullptr; 1970 if (IsConstructor()) accumulator->Add("new "); 1971 accumulator->PrintFunction(function, receiver, &code); 1972 accumulator->Add(" [%p]", function); 1973 1974 // Get scope information for nicer output, if possible. If code is nullptr, or 1975 // doesn't contain scope info, scope_info will return 0 for the number of 1976 // parameters, stack local variables, context local variables, stack slots, 1977 // or context slots. 1978 SharedFunctionInfo* shared = function->shared(); 1979 ScopeInfo* scope_info = shared->scope_info(); 1980 Object* script_obj = shared->script(); 1981 if (script_obj->IsScript()) { 1982 Script* script = Script::cast(script_obj); 1983 accumulator->Add(" ["); 1984 accumulator->PrintName(script->name()); 1985 1986 if (is_interpreted()) { 1987 const InterpretedFrame* iframe = 1988 reinterpret_cast<const InterpretedFrame*>(this); 1989 BytecodeArray* bytecodes = iframe->GetBytecodeArray(); 1990 int offset = iframe->GetBytecodeOffset(); 1991 int source_pos = AbstractCode::cast(bytecodes)->SourcePosition(offset); 1992 int line = script->GetLineNumber(source_pos) + 1; 1993 accumulator->Add(":%d] [bytecode=%p offset=%d]", line, bytecodes, offset); 1994 } else { 1995 int function_start_pos = shared->StartPosition(); 1996 int line = script->GetLineNumber(function_start_pos) + 1; 1997 accumulator->Add(":~%d] [pc=%p]", line, reinterpret_cast<void*>(pc())); 1998 } 1999 } 2000 2001 accumulator->Add("(this=%o", receiver); 2002 2003 // Print the parameters. 2004 int parameters_count = ComputeParametersCount(); 2005 for (int i = 0; i < parameters_count; i++) { 2006 accumulator->Add(","); 2007 accumulator->Add("%o", GetParameter(i)); 2008 } 2009 2010 accumulator->Add(")"); 2011 if (mode == OVERVIEW) { 2012 accumulator->Add("\n"); 2013 return; 2014 } 2015 if (is_optimized()) { 2016 accumulator->Add(" {\n// optimized frame\n"); 2017 PrintFunctionSource(accumulator, shared, code); 2018 accumulator->Add("}\n"); 2019 return; 2020 } 2021 accumulator->Add(" {\n"); 2022 2023 // Compute the number of locals and expression stack elements. 2024 int heap_locals_count = scope_info->ContextLocalCount(); 2025 int expressions_count = ComputeExpressionsCount(); 2026 2027 // Try to get hold of the context of this frame. 2028 Context* context = nullptr; 2029 if (this->context() != nullptr && this->context()->IsContext()) { 2030 context = Context::cast(this->context()); 2031 while (context->IsWithContext()) { 2032 context = context->previous(); 2033 DCHECK_NOT_NULL(context); 2034 } 2035 } 2036 2037 // Print heap-allocated local variables. 2038 if (heap_locals_count > 0) { 2039 accumulator->Add(" // heap-allocated locals\n"); 2040 } 2041 for (int i = 0; i < heap_locals_count; i++) { 2042 accumulator->Add(" var "); 2043 accumulator->PrintName(scope_info->ContextLocalName(i)); 2044 accumulator->Add(" = "); 2045 if (context != nullptr) { 2046 int index = Context::MIN_CONTEXT_SLOTS + i; 2047 if (index < context->length()) { 2048 accumulator->Add("%o", context->get(index)); 2049 } else { 2050 accumulator->Add( 2051 "// warning: missing context slot - inconsistent frame?"); 2052 } 2053 } else { 2054 accumulator->Add("// warning: no context found - inconsistent frame?"); 2055 } 2056 accumulator->Add("\n"); 2057 } 2058 2059 // Print the expression stack. 2060 if (0 < expressions_count) { 2061 accumulator->Add(" // expression stack (top to bottom)\n"); 2062 } 2063 for (int i = expressions_count - 1; i >= 0; i--) { 2064 accumulator->Add(" [%02d] : %o\n", i, GetExpression(i)); 2065 } 2066 2067 PrintFunctionSource(accumulator, shared, code); 2068 2069 accumulator->Add("}\n\n"); 2070 } 2071 2072 2073 void ArgumentsAdaptorFrame::Print(StringStream* accumulator, 2074 PrintMode mode, 2075 int index) const { 2076 int actual = ComputeParametersCount(); 2077 int expected = -1; 2078 JSFunction* function = this->function(); 2079 expected = function->shared()->internal_formal_parameter_count(); 2080 2081 PrintIndex(accumulator, mode, index); 2082 accumulator->Add("arguments adaptor frame: %d->%d", actual, expected); 2083 if (mode == OVERVIEW) { 2084 accumulator->Add("\n"); 2085 return; 2086 } 2087 accumulator->Add(" {\n"); 2088 2089 // Print actual arguments. 2090 if (actual > 0) accumulator->Add(" // actual arguments\n"); 2091 for (int i = 0; i < actual; i++) { 2092 accumulator->Add(" [%02d] : %o", i, GetParameter(i)); 2093 if (expected != -1 && i >= expected) { 2094 accumulator->Add(" // not passed to callee"); 2095 } 2096 accumulator->Add("\n"); 2097 } 2098 2099 accumulator->Add("}\n\n"); 2100 } 2101 2102 void EntryFrame::Iterate(RootVisitor* v) const { 2103 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 2104 } 2105 2106 void StandardFrame::IterateExpressions(RootVisitor* v) const { 2107 const int offset = StandardFrameConstants::kLastObjectOffset; 2108 Object** base = &Memory<Object*>(sp()); 2109 Object** limit = &Memory<Object*>(fp() + offset) + 1; 2110 v->VisitRootPointers(Root::kTop, nullptr, base, limit); 2111 } 2112 2113 void JavaScriptFrame::Iterate(RootVisitor* v) const { 2114 IterateExpressions(v); 2115 IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 2116 } 2117 2118 void InternalFrame::Iterate(RootVisitor* v) const { 2119 Code* code = LookupCode(); 2120 IteratePc(v, pc_address(), constant_pool_address(), code); 2121 // Internal frames typically do not receive any arguments, hence their stack 2122 // only contains tagged pointers. 2123 // We are misusing the has_tagged_params flag here to tell us whether 2124 // the full stack frame contains only tagged pointers or only raw values. 2125 // This is used for the WasmCompileLazy builtin, where we actually pass 2126 // untagged arguments and also store untagged values on the stack. 2127 if (code->has_tagged_params()) IterateExpressions(v); 2128 } 2129 2130 // ------------------------------------------------------------------------- 2131 2132 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* 2133 InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) { 2134 isolate_->counters()->pc_to_code()->Increment(); 2135 DCHECK(base::bits::IsPowerOfTwo(kInnerPointerToCodeCacheSize)); 2136 uint32_t hash = ComputeIntegerHash( 2137 ObjectAddressForHashing(reinterpret_cast<void*>(inner_pointer))); 2138 uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1); 2139 InnerPointerToCodeCacheEntry* entry = cache(index); 2140 if (entry->inner_pointer == inner_pointer) { 2141 isolate_->counters()->pc_to_code_cached()->Increment(); 2142 DCHECK(entry->code == 2143 isolate_->heap()->GcSafeFindCodeForInnerPointer(inner_pointer)); 2144 } else { 2145 // Because this code may be interrupted by a profiling signal that 2146 // also queries the cache, we cannot update inner_pointer before the code 2147 // has been set. Otherwise, we risk trying to use a cache entry before 2148 // the code has been computed. 2149 entry->code = 2150 isolate_->heap()->GcSafeFindCodeForInnerPointer(inner_pointer); 2151 entry->safepoint_entry.Reset(); 2152 entry->inner_pointer = inner_pointer; 2153 } 2154 return entry; 2155 } 2156 } // namespace internal 2157 } // namespace v8 2158