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