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