LCOV - code coverage report
Current view: top level - src - frames.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 721 937 76.9 %
Date: 2019-02-19 Functions: 133 190 70.0 %

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

Generated by: LCOV version 1.10