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