11cb0ef41Sopenharmony_ci// Copyright 2012 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/execution/frames.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <memory> 81cb0ef41Sopenharmony_ci#include <sstream> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include "src/base/bits.h" 111cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors.h" 131cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h" 141cb0ef41Sopenharmony_ci#include "src/codegen/register-configuration.h" 151cb0ef41Sopenharmony_ci#include "src/codegen/safepoint-table.h" 161cb0ef41Sopenharmony_ci#include "src/common/globals.h" 171cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimizer.h" 181cb0ef41Sopenharmony_ci#include "src/execution/frames-inl.h" 191cb0ef41Sopenharmony_ci#include "src/execution/vm-state-inl.h" 201cb0ef41Sopenharmony_ci#include "src/ic/ic-stats.h" 211cb0ef41Sopenharmony_ci#include "src/logging/counters.h" 221cb0ef41Sopenharmony_ci#include "src/objects/code.h" 231cb0ef41Sopenharmony_ci#include "src/objects/slots.h" 241cb0ef41Sopenharmony_ci#include "src/objects/smi.h" 251cb0ef41Sopenharmony_ci#include "src/objects/visitors.h" 261cb0ef41Sopenharmony_ci#include "src/snapshot/embedded/embedded-data-inl.h" 271cb0ef41Sopenharmony_ci#include "src/strings/string-stream.h" 281cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h" 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 311cb0ef41Sopenharmony_ci#include "src/debug/debug-wasm-objects.h" 321cb0ef41Sopenharmony_ci#include "src/wasm/wasm-code-manager.h" 331cb0ef41Sopenharmony_ci#include "src/wasm/wasm-engine.h" 341cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects-inl.h" 351cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_cinamespace v8 { 381cb0ef41Sopenharmony_cinamespace internal { 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ciReturnAddressLocationResolver StackFrame::return_address_location_resolver_ = 411cb0ef41Sopenharmony_ci nullptr; 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_cinamespace { 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ciAddress AddressOf(const StackHandler* handler) { 461cb0ef41Sopenharmony_ci Address raw = handler->address(); 471cb0ef41Sopenharmony_ci#ifdef V8_USE_ADDRESS_SANITIZER 481cb0ef41Sopenharmony_ci // ASan puts C++-allocated StackHandler markers onto its fake stack. 491cb0ef41Sopenharmony_ci // We work around that by storing the real stack address in the "padding" 501cb0ef41Sopenharmony_ci // field. StackHandlers allocated from generated code have 0 as padding. 511cb0ef41Sopenharmony_ci Address padding = 521cb0ef41Sopenharmony_ci base::Memory<Address>(raw + StackHandlerConstants::kPaddingOffset); 531cb0ef41Sopenharmony_ci if (padding != 0) return padding; 541cb0ef41Sopenharmony_ci#endif 551cb0ef41Sopenharmony_ci return raw; 561cb0ef41Sopenharmony_ci} 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci} // namespace 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ci// Iterator that supports traversing the stack handlers of a 611cb0ef41Sopenharmony_ci// particular frame. Needs to know the top of the handler chain. 621cb0ef41Sopenharmony_ciclass StackHandlerIterator { 631cb0ef41Sopenharmony_ci public: 641cb0ef41Sopenharmony_ci StackHandlerIterator(const StackFrame* frame, StackHandler* handler) 651cb0ef41Sopenharmony_ci : limit_(frame->fp()), handler_(handler) { 661cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 671cb0ef41Sopenharmony_ci // Make sure the handler has already been unwound to this frame. With stack 681cb0ef41Sopenharmony_ci // switching this is not equivalent to the inequality below, because the 691cb0ef41Sopenharmony_ci // frame and the handler could be in different stacks. 701cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!FLAG_experimental_wasm_stack_switching, 711cb0ef41Sopenharmony_ci frame->sp() <= AddressOf(handler)); 721cb0ef41Sopenharmony_ci // For CWasmEntry frames, the handler was registered by the last C++ 731cb0ef41Sopenharmony_ci // frame (Execution::CallWasm), so even though its address is already 741cb0ef41Sopenharmony_ci // beyond the limit, we know we always want to unwind one handler. 751cb0ef41Sopenharmony_ci if (frame->is_c_wasm_entry()) handler_ = handler_->next(); 761cb0ef41Sopenharmony_ci#else 771cb0ef41Sopenharmony_ci // Make sure the handler has already been unwound to this frame. 781cb0ef41Sopenharmony_ci DCHECK_LE(frame->sp(), AddressOf(handler)); 791cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci StackHandler* handler() const { return handler_; } 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci bool done() { return handler_ == nullptr || AddressOf(handler_) > limit_; } 851cb0ef41Sopenharmony_ci void Advance() { 861cb0ef41Sopenharmony_ci DCHECK(!done()); 871cb0ef41Sopenharmony_ci handler_ = handler_->next(); 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci private: 911cb0ef41Sopenharmony_ci const Address limit_; 921cb0ef41Sopenharmony_ci StackHandler* handler_; 931cb0ef41Sopenharmony_ci}; 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci// ------------------------------------------------------------------------- 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci#define INITIALIZE_SINGLETON(type, field) field##_(this), 981cb0ef41Sopenharmony_ciStackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate, 991cb0ef41Sopenharmony_ci bool can_access_heap_objects) 1001cb0ef41Sopenharmony_ci : isolate_(isolate), 1011cb0ef41Sopenharmony_ci STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) frame_(nullptr), 1021cb0ef41Sopenharmony_ci handler_(nullptr), 1031cb0ef41Sopenharmony_ci can_access_heap_objects_(can_access_heap_objects) {} 1041cb0ef41Sopenharmony_ci#undef INITIALIZE_SINGLETON 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ciStackFrameIterator::StackFrameIterator(Isolate* isolate) 1071cb0ef41Sopenharmony_ci : StackFrameIterator(isolate, isolate->thread_local_top()) {} 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ciStackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t) 1101cb0ef41Sopenharmony_ci : StackFrameIteratorBase(isolate, true) { 1111cb0ef41Sopenharmony_ci Reset(t); 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 1141cb0ef41Sopenharmony_ciStackFrameIterator::StackFrameIterator(Isolate* isolate, 1151cb0ef41Sopenharmony_ci wasm::StackMemory* stack) 1161cb0ef41Sopenharmony_ci : StackFrameIteratorBase(isolate, true) { 1171cb0ef41Sopenharmony_ci Reset(isolate->thread_local_top(), stack); 1181cb0ef41Sopenharmony_ci} 1191cb0ef41Sopenharmony_ci#endif 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_civoid StackFrameIterator::Advance() { 1221cb0ef41Sopenharmony_ci DCHECK(!done()); 1231cb0ef41Sopenharmony_ci // Compute the state of the calling frame before restoring 1241cb0ef41Sopenharmony_ci // callee-saved registers and unwinding handlers. This allows the 1251cb0ef41Sopenharmony_ci // frame code that computes the caller state to access the top 1261cb0ef41Sopenharmony_ci // handler and the value of any callee-saved register if needed. 1271cb0ef41Sopenharmony_ci StackFrame::State state; 1281cb0ef41Sopenharmony_ci StackFrame::Type type = frame_->GetCallerState(&state); 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci // Unwind handlers corresponding to the current frame. 1311cb0ef41Sopenharmony_ci StackHandlerIterator it(frame_, handler_); 1321cb0ef41Sopenharmony_ci while (!it.done()) it.Advance(); 1331cb0ef41Sopenharmony_ci handler_ = it.handler(); 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci // Advance to the calling frame. 1361cb0ef41Sopenharmony_ci frame_ = SingletonFor(type, &state); 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci // When we're done iterating over the stack frames, the handler 1391cb0ef41Sopenharmony_ci // chain must have been completely unwound. Except for wasm stack-switching: 1401cb0ef41Sopenharmony_ci // we stop at the end of the current segment. 1411cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 1421cb0ef41Sopenharmony_ci DCHECK_IMPLIES(done() && !FLAG_experimental_wasm_stack_switching, 1431cb0ef41Sopenharmony_ci handler_ == nullptr); 1441cb0ef41Sopenharmony_ci#else 1451cb0ef41Sopenharmony_ci DCHECK_IMPLIES(done(), handler_ == nullptr); 1461cb0ef41Sopenharmony_ci#endif 1471cb0ef41Sopenharmony_ci} 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ciStackFrame* StackFrameIterator::Reframe() { 1501cb0ef41Sopenharmony_ci StackFrame::Type type = frame_->ComputeType(this, &frame_->state_); 1511cb0ef41Sopenharmony_ci frame_ = SingletonFor(type, &frame_->state_); 1521cb0ef41Sopenharmony_ci return frame(); 1531cb0ef41Sopenharmony_ci} 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_civoid StackFrameIterator::Reset(ThreadLocalTop* top) { 1561cb0ef41Sopenharmony_ci StackFrame::State state; 1571cb0ef41Sopenharmony_ci StackFrame::Type type = 1581cb0ef41Sopenharmony_ci ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); 1591cb0ef41Sopenharmony_ci handler_ = StackHandler::FromAddress(Isolate::handler(top)); 1601cb0ef41Sopenharmony_ci frame_ = SingletonFor(type, &state); 1611cb0ef41Sopenharmony_ci} 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 1641cb0ef41Sopenharmony_civoid StackFrameIterator::Reset(ThreadLocalTop* top, wasm::StackMemory* stack) { 1651cb0ef41Sopenharmony_ci if (stack->jmpbuf()->sp == kNullAddress) { 1661cb0ef41Sopenharmony_ci // A null SP indicates that the computation associated with this stack has 1671cb0ef41Sopenharmony_ci // returned, leaving the stack segment empty. 1681cb0ef41Sopenharmony_ci return; 1691cb0ef41Sopenharmony_ci } 1701cb0ef41Sopenharmony_ci StackFrame::State state; 1711cb0ef41Sopenharmony_ci StackSwitchFrame::GetStateForJumpBuffer(stack->jmpbuf(), &state); 1721cb0ef41Sopenharmony_ci handler_ = StackHandler::FromAddress(Isolate::handler(top)); 1731cb0ef41Sopenharmony_ci frame_ = SingletonFor(StackFrame::STACK_SWITCH, &state); 1741cb0ef41Sopenharmony_ci} 1751cb0ef41Sopenharmony_ci#endif 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ciStackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type, 1781cb0ef41Sopenharmony_ci StackFrame::State* state) { 1791cb0ef41Sopenharmony_ci StackFrame* result = SingletonFor(type); 1801cb0ef41Sopenharmony_ci DCHECK((!result) == (type == StackFrame::NO_FRAME_TYPE)); 1811cb0ef41Sopenharmony_ci if (result) result->state_ = *state; 1821cb0ef41Sopenharmony_ci return result; 1831cb0ef41Sopenharmony_ci} 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ciStackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) { 1861cb0ef41Sopenharmony_ci#define FRAME_TYPE_CASE(type, field) \ 1871cb0ef41Sopenharmony_ci case StackFrame::type: \ 1881cb0ef41Sopenharmony_ci return &field##_; 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci switch (type) { 1911cb0ef41Sopenharmony_ci case StackFrame::NO_FRAME_TYPE: 1921cb0ef41Sopenharmony_ci return nullptr; 1931cb0ef41Sopenharmony_ci STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE) 1941cb0ef41Sopenharmony_ci default: 1951cb0ef41Sopenharmony_ci break; 1961cb0ef41Sopenharmony_ci } 1971cb0ef41Sopenharmony_ci return nullptr; 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci#undef FRAME_TYPE_CASE 2001cb0ef41Sopenharmony_ci} 2011cb0ef41Sopenharmony_ci 2021cb0ef41Sopenharmony_ci// ------------------------------------------------------------------------- 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_civoid TypedFrameWithJSLinkage::Iterate(RootVisitor* v) const { 2051cb0ef41Sopenharmony_ci IterateExpressions(v); 2061cb0ef41Sopenharmony_ci IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 2071cb0ef41Sopenharmony_ci} 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci// ------------------------------------------------------------------------- 2101cb0ef41Sopenharmony_ci 2111cb0ef41Sopenharmony_civoid JavaScriptFrameIterator::Advance() { 2121cb0ef41Sopenharmony_ci do { 2131cb0ef41Sopenharmony_ci iterator_.Advance(); 2141cb0ef41Sopenharmony_ci } while (!iterator_.done() && !iterator_.frame()->is_java_script()); 2151cb0ef41Sopenharmony_ci} 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci// ------------------------------------------------------------------------- 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ciStackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate) 2201cb0ef41Sopenharmony_ci : iterator_(isolate) { 2211cb0ef41Sopenharmony_ci if (!done() && !IsValidFrame(iterator_.frame())) Advance(); 2221cb0ef41Sopenharmony_ci} 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ciStackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate, 2251cb0ef41Sopenharmony_ci StackFrameId id) 2261cb0ef41Sopenharmony_ci : StackTraceFrameIterator(isolate) { 2271cb0ef41Sopenharmony_ci while (!done() && frame()->id() != id) Advance(); 2281cb0ef41Sopenharmony_ci} 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_civoid StackTraceFrameIterator::Advance() { 2311cb0ef41Sopenharmony_ci do { 2321cb0ef41Sopenharmony_ci iterator_.Advance(); 2331cb0ef41Sopenharmony_ci } while (!done() && !IsValidFrame(iterator_.frame())); 2341cb0ef41Sopenharmony_ci} 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ciint StackTraceFrameIterator::FrameFunctionCount() const { 2371cb0ef41Sopenharmony_ci DCHECK(!done()); 2381cb0ef41Sopenharmony_ci if (!iterator_.frame()->is_optimized()) return 1; 2391cb0ef41Sopenharmony_ci std::vector<SharedFunctionInfo> infos; 2401cb0ef41Sopenharmony_ci OptimizedFrame::cast(iterator_.frame())->GetFunctions(&infos); 2411cb0ef41Sopenharmony_ci return static_cast<int>(infos.size()); 2421cb0ef41Sopenharmony_ci} 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ciFrameSummary StackTraceFrameIterator::GetTopValidFrame() const { 2451cb0ef41Sopenharmony_ci DCHECK(!done()); 2461cb0ef41Sopenharmony_ci // Like FrameSummary::GetTop, but additionally observes 2471cb0ef41Sopenharmony_ci // StackTraceFrameIterator filtering semantics. 2481cb0ef41Sopenharmony_ci std::vector<FrameSummary> frames; 2491cb0ef41Sopenharmony_ci frame()->Summarize(&frames); 2501cb0ef41Sopenharmony_ci if (is_javascript()) { 2511cb0ef41Sopenharmony_ci for (int i = static_cast<int>(frames.size()) - 1; i >= 0; i--) { 2521cb0ef41Sopenharmony_ci if (!IsValidJSFunction(*frames[i].AsJavaScript().function())) continue; 2531cb0ef41Sopenharmony_ci return frames[i]; 2541cb0ef41Sopenharmony_ci } 2551cb0ef41Sopenharmony_ci UNREACHABLE(); 2561cb0ef41Sopenharmony_ci } 2571cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 2581cb0ef41Sopenharmony_ci if (is_wasm()) return frames.back(); 2591cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 2601cb0ef41Sopenharmony_ci UNREACHABLE(); 2611cb0ef41Sopenharmony_ci} 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci// static 2641cb0ef41Sopenharmony_cibool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) { 2651cb0ef41Sopenharmony_ci if (frame->is_java_script()) { 2661cb0ef41Sopenharmony_ci return IsValidJSFunction(static_cast<JavaScriptFrame*>(frame)->function()); 2671cb0ef41Sopenharmony_ci } 2681cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 2691cb0ef41Sopenharmony_ci if (frame->is_wasm()) return true; 2701cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 2711cb0ef41Sopenharmony_ci return false; 2721cb0ef41Sopenharmony_ci} 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci// static 2751cb0ef41Sopenharmony_cibool StackTraceFrameIterator::IsValidJSFunction(JSFunction f) { 2761cb0ef41Sopenharmony_ci if (!f.IsJSFunction()) return false; 2771cb0ef41Sopenharmony_ci return f.shared().IsSubjectToDebugging(); 2781cb0ef41Sopenharmony_ci} 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci// ------------------------------------------------------------------------- 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_cinamespace { 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_cibool IsInterpreterFramePc(Isolate* isolate, Address pc, 2851cb0ef41Sopenharmony_ci StackFrame::State* state) { 2861cb0ef41Sopenharmony_ci Builtin builtin = OffHeapInstructionStream::TryLookupCode(isolate, pc); 2871cb0ef41Sopenharmony_ci if (builtin != Builtin::kNoBuiltinId && 2881cb0ef41Sopenharmony_ci (builtin == Builtin::kInterpreterEntryTrampoline || 2891cb0ef41Sopenharmony_ci builtin == Builtin::kInterpreterEnterAtBytecode || 2901cb0ef41Sopenharmony_ci builtin == Builtin::kInterpreterEnterAtNextBytecode || 2911cb0ef41Sopenharmony_ci builtin == Builtin::kBaselineOrInterpreterEnterAtBytecode || 2921cb0ef41Sopenharmony_ci builtin == Builtin::kBaselineOrInterpreterEnterAtNextBytecode)) { 2931cb0ef41Sopenharmony_ci return true; 2941cb0ef41Sopenharmony_ci } else if (FLAG_interpreted_frames_native_stack) { 2951cb0ef41Sopenharmony_ci intptr_t marker = Memory<intptr_t>( 2961cb0ef41Sopenharmony_ci state->fp + CommonFrameConstants::kContextOrFrameTypeOffset); 2971cb0ef41Sopenharmony_ci MSAN_MEMORY_IS_INITIALIZED( 2981cb0ef41Sopenharmony_ci state->fp + StandardFrameConstants::kFunctionOffset, 2991cb0ef41Sopenharmony_ci kSystemPointerSize); 3001cb0ef41Sopenharmony_ci Object maybe_function = Object( 3011cb0ef41Sopenharmony_ci Memory<Address>(state->fp + StandardFrameConstants::kFunctionOffset)); 3021cb0ef41Sopenharmony_ci // There's no need to run a full ContainsSlow if we know the frame can't be 3031cb0ef41Sopenharmony_ci // an InterpretedFrame, so we do these fast checks first 3041cb0ef41Sopenharmony_ci if (StackFrame::IsTypeMarker(marker) || maybe_function.IsSmi()) { 3051cb0ef41Sopenharmony_ci return false; 3061cb0ef41Sopenharmony_ci } else if (!isolate->heap()->InSpaceSlow(pc, CODE_SPACE)) { 3071cb0ef41Sopenharmony_ci return false; 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci Code interpreter_entry_trampoline = 3101cb0ef41Sopenharmony_ci isolate->heap()->GcSafeFindCodeForInnerPointer(pc); 3111cb0ef41Sopenharmony_ci return interpreter_entry_trampoline.is_interpreter_trampoline_builtin(); 3121cb0ef41Sopenharmony_ci } else { 3131cb0ef41Sopenharmony_ci return false; 3141cb0ef41Sopenharmony_ci } 3151cb0ef41Sopenharmony_ci} 3161cb0ef41Sopenharmony_ci 3171cb0ef41Sopenharmony_ci} // namespace 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_cibool SafeStackFrameIterator::IsNoFrameBytecodeHandlerPc(Isolate* isolate, 3201cb0ef41Sopenharmony_ci Address pc, 3211cb0ef41Sopenharmony_ci Address fp) const { 3221cb0ef41Sopenharmony_ci // Return false for builds with non-embedded bytecode handlers. 3231cb0ef41Sopenharmony_ci if (Isolate::CurrentEmbeddedBlobCode() == nullptr) return false; 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci EmbeddedData d = EmbeddedData::FromBlob(isolate); 3261cb0ef41Sopenharmony_ci if (pc < d.InstructionStartOfBytecodeHandlers() || 3271cb0ef41Sopenharmony_ci pc >= d.InstructionEndOfBytecodeHandlers()) { 3281cb0ef41Sopenharmony_ci // Not a bytecode handler pc address. 3291cb0ef41Sopenharmony_ci return false; 3301cb0ef41Sopenharmony_ci } 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci if (!IsValidStackAddress(fp + 3331cb0ef41Sopenharmony_ci CommonFrameConstants::kContextOrFrameTypeOffset)) { 3341cb0ef41Sopenharmony_ci return false; 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci // Check if top stack frame is a bytecode handler stub frame. 3381cb0ef41Sopenharmony_ci MSAN_MEMORY_IS_INITIALIZED( 3391cb0ef41Sopenharmony_ci fp + CommonFrameConstants::kContextOrFrameTypeOffset, kSystemPointerSize); 3401cb0ef41Sopenharmony_ci intptr_t marker = 3411cb0ef41Sopenharmony_ci Memory<intptr_t>(fp + CommonFrameConstants::kContextOrFrameTypeOffset); 3421cb0ef41Sopenharmony_ci if (StackFrame::IsTypeMarker(marker) && 3431cb0ef41Sopenharmony_ci StackFrame::MarkerToType(marker) == StackFrame::STUB) { 3441cb0ef41Sopenharmony_ci // Bytecode handler built a frame. 3451cb0ef41Sopenharmony_ci return false; 3461cb0ef41Sopenharmony_ci } 3471cb0ef41Sopenharmony_ci return true; 3481cb0ef41Sopenharmony_ci} 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ciSafeStackFrameIterator::SafeStackFrameIterator(Isolate* isolate, Address pc, 3511cb0ef41Sopenharmony_ci Address fp, Address sp, 3521cb0ef41Sopenharmony_ci Address lr, Address js_entry_sp) 3531cb0ef41Sopenharmony_ci : StackFrameIteratorBase(isolate, false), 3541cb0ef41Sopenharmony_ci low_bound_(sp), 3551cb0ef41Sopenharmony_ci high_bound_(js_entry_sp), 3561cb0ef41Sopenharmony_ci top_frame_type_(StackFrame::NO_FRAME_TYPE), 3571cb0ef41Sopenharmony_ci top_context_address_(kNullAddress), 3581cb0ef41Sopenharmony_ci external_callback_scope_(isolate->external_callback_scope()), 3591cb0ef41Sopenharmony_ci top_link_register_(lr) { 3601cb0ef41Sopenharmony_ci StackFrame::State state; 3611cb0ef41Sopenharmony_ci StackFrame::Type type; 3621cb0ef41Sopenharmony_ci ThreadLocalTop* top = isolate->thread_local_top(); 3631cb0ef41Sopenharmony_ci bool advance_frame = true; 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci Address fast_c_fp = isolate->isolate_data()->fast_c_call_caller_fp(); 3661cb0ef41Sopenharmony_ci uint8_t stack_is_iterable = isolate->isolate_data()->stack_is_iterable(); 3671cb0ef41Sopenharmony_ci if (!stack_is_iterable) { 3681cb0ef41Sopenharmony_ci frame_ = nullptr; 3691cb0ef41Sopenharmony_ci return; 3701cb0ef41Sopenharmony_ci } 3711cb0ef41Sopenharmony_ci // 'Fast C calls' are a special type of C call where we call directly from 3721cb0ef41Sopenharmony_ci // JS to C without an exit frame inbetween. The CEntryStub is responsible 3731cb0ef41Sopenharmony_ci // for setting Isolate::c_entry_fp, meaning that it won't be set for fast C 3741cb0ef41Sopenharmony_ci // calls. To keep the stack iterable, we store the FP and PC of the caller 3751cb0ef41Sopenharmony_ci // of the fast C call on the isolate. This is guaranteed to be the topmost 3761cb0ef41Sopenharmony_ci // JS frame, because fast C calls cannot call back into JS. We start 3771cb0ef41Sopenharmony_ci // iterating the stack from this topmost JS frame. 3781cb0ef41Sopenharmony_ci if (fast_c_fp) { 3791cb0ef41Sopenharmony_ci DCHECK_NE(kNullAddress, isolate->isolate_data()->fast_c_call_caller_pc()); 3801cb0ef41Sopenharmony_ci type = StackFrame::Type::OPTIMIZED; 3811cb0ef41Sopenharmony_ci top_frame_type_ = type; 3821cb0ef41Sopenharmony_ci state.fp = fast_c_fp; 3831cb0ef41Sopenharmony_ci state.sp = sp; 3841cb0ef41Sopenharmony_ci state.pc_address = reinterpret_cast<Address*>( 3851cb0ef41Sopenharmony_ci isolate->isolate_data()->fast_c_call_caller_pc_address()); 3861cb0ef41Sopenharmony_ci advance_frame = false; 3871cb0ef41Sopenharmony_ci } else if (IsValidTop(top)) { 3881cb0ef41Sopenharmony_ci type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state); 3891cb0ef41Sopenharmony_ci top_frame_type_ = type; 3901cb0ef41Sopenharmony_ci } else if (IsValidStackAddress(fp)) { 3911cb0ef41Sopenharmony_ci DCHECK_NE(fp, kNullAddress); 3921cb0ef41Sopenharmony_ci state.fp = fp; 3931cb0ef41Sopenharmony_ci state.sp = sp; 3941cb0ef41Sopenharmony_ci state.pc_address = StackFrame::ResolveReturnAddressLocation( 3951cb0ef41Sopenharmony_ci reinterpret_cast<Address*>(CommonFrame::ComputePCAddress(fp))); 3961cb0ef41Sopenharmony_ci 3971cb0ef41Sopenharmony_ci // If the current PC is in a bytecode handler, the top stack frame isn't 3981cb0ef41Sopenharmony_ci // the bytecode handler's frame and the top of stack or link register is a 3991cb0ef41Sopenharmony_ci // return address into the interpreter entry trampoline, then we are likely 4001cb0ef41Sopenharmony_ci // in a bytecode handler with elided frame. In that case, set the PC 4011cb0ef41Sopenharmony_ci // properly and make sure we do not drop the frame. 4021cb0ef41Sopenharmony_ci bool is_no_frame_bytecode_handler = false; 4031cb0ef41Sopenharmony_ci if (IsNoFrameBytecodeHandlerPc(isolate, pc, fp)) { 4041cb0ef41Sopenharmony_ci Address* tos_location = nullptr; 4051cb0ef41Sopenharmony_ci if (top_link_register_) { 4061cb0ef41Sopenharmony_ci tos_location = &top_link_register_; 4071cb0ef41Sopenharmony_ci } else if (IsValidStackAddress(sp)) { 4081cb0ef41Sopenharmony_ci MSAN_MEMORY_IS_INITIALIZED(sp, kSystemPointerSize); 4091cb0ef41Sopenharmony_ci tos_location = reinterpret_cast<Address*>(sp); 4101cb0ef41Sopenharmony_ci } 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci if (IsInterpreterFramePc(isolate, *tos_location, &state)) { 4131cb0ef41Sopenharmony_ci state.pc_address = tos_location; 4141cb0ef41Sopenharmony_ci is_no_frame_bytecode_handler = true; 4151cb0ef41Sopenharmony_ci advance_frame = false; 4161cb0ef41Sopenharmony_ci } 4171cb0ef41Sopenharmony_ci } 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset, 4201cb0ef41Sopenharmony_ci // we check only that kMarkerOffset is within the stack bounds and do 4211cb0ef41Sopenharmony_ci // compile time check that kContextOffset slot is pushed on the stack before 4221cb0ef41Sopenharmony_ci // kMarkerOffset. 4231cb0ef41Sopenharmony_ci STATIC_ASSERT(StandardFrameConstants::kFunctionOffset < 4241cb0ef41Sopenharmony_ci StandardFrameConstants::kContextOffset); 4251cb0ef41Sopenharmony_ci Address frame_marker = fp + StandardFrameConstants::kFunctionOffset; 4261cb0ef41Sopenharmony_ci if (IsValidStackAddress(frame_marker)) { 4271cb0ef41Sopenharmony_ci if (is_no_frame_bytecode_handler) { 4281cb0ef41Sopenharmony_ci type = StackFrame::INTERPRETED; 4291cb0ef41Sopenharmony_ci } else { 4301cb0ef41Sopenharmony_ci type = StackFrame::ComputeType(this, &state); 4311cb0ef41Sopenharmony_ci } 4321cb0ef41Sopenharmony_ci top_frame_type_ = type; 4331cb0ef41Sopenharmony_ci MSAN_MEMORY_IS_INITIALIZED( 4341cb0ef41Sopenharmony_ci fp + CommonFrameConstants::kContextOrFrameTypeOffset, 4351cb0ef41Sopenharmony_ci kSystemPointerSize); 4361cb0ef41Sopenharmony_ci Address type_or_context_address = 4371cb0ef41Sopenharmony_ci Memory<Address>(fp + CommonFrameConstants::kContextOrFrameTypeOffset); 4381cb0ef41Sopenharmony_ci if (!StackFrame::IsTypeMarker(type_or_context_address)) 4391cb0ef41Sopenharmony_ci top_context_address_ = type_or_context_address; 4401cb0ef41Sopenharmony_ci } else { 4411cb0ef41Sopenharmony_ci // Mark the frame as OPTIMIZED if we cannot determine its type. 4421cb0ef41Sopenharmony_ci // We chose OPTIMIZED rather than INTERPRETED because it's closer to 4431cb0ef41Sopenharmony_ci // the original value of StackFrame::JAVA_SCRIPT here, in that JAVA_SCRIPT 4441cb0ef41Sopenharmony_ci // referred to full-codegen frames (now removed from the tree), and 4451cb0ef41Sopenharmony_ci // OPTIMIZED refers to turbofan frames, both of which are generated 4461cb0ef41Sopenharmony_ci // code. INTERPRETED frames refer to bytecode. 4471cb0ef41Sopenharmony_ci // The frame anyways will be skipped. 4481cb0ef41Sopenharmony_ci type = StackFrame::OPTIMIZED; 4491cb0ef41Sopenharmony_ci // Top frame is incomplete so we cannot reliably determine its type. 4501cb0ef41Sopenharmony_ci top_frame_type_ = StackFrame::NO_FRAME_TYPE; 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci } else { 4531cb0ef41Sopenharmony_ci return; 4541cb0ef41Sopenharmony_ci } 4551cb0ef41Sopenharmony_ci frame_ = SingletonFor(type, &state); 4561cb0ef41Sopenharmony_ci if (advance_frame && frame_) Advance(); 4571cb0ef41Sopenharmony_ci} 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_cibool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const { 4601cb0ef41Sopenharmony_ci Address c_entry_fp = Isolate::c_entry_fp(top); 4611cb0ef41Sopenharmony_ci if (!IsValidExitFrame(c_entry_fp)) return false; 4621cb0ef41Sopenharmony_ci // There should be at least one JS_ENTRY stack handler. 4631cb0ef41Sopenharmony_ci Address handler = Isolate::handler(top); 4641cb0ef41Sopenharmony_ci if (handler == kNullAddress) return false; 4651cb0ef41Sopenharmony_ci // Check that there are no js frames on top of the native frames. 4661cb0ef41Sopenharmony_ci return c_entry_fp < handler; 4671cb0ef41Sopenharmony_ci} 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_civoid SafeStackFrameIterator::AdvanceOneFrame() { 4701cb0ef41Sopenharmony_ci DCHECK(!done()); 4711cb0ef41Sopenharmony_ci StackFrame* last_frame = frame_; 4721cb0ef41Sopenharmony_ci Address last_sp = last_frame->sp(), last_fp = last_frame->fp(); 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci // Before advancing to the next stack frame, perform pointer validity tests. 4751cb0ef41Sopenharmony_ci if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) { 4761cb0ef41Sopenharmony_ci frame_ = nullptr; 4771cb0ef41Sopenharmony_ci return; 4781cb0ef41Sopenharmony_ci } 4791cb0ef41Sopenharmony_ci 4801cb0ef41Sopenharmony_ci // Advance to the previous frame. 4811cb0ef41Sopenharmony_ci StackFrame::State state; 4821cb0ef41Sopenharmony_ci StackFrame::Type type = frame_->GetCallerState(&state); 4831cb0ef41Sopenharmony_ci frame_ = SingletonFor(type, &state); 4841cb0ef41Sopenharmony_ci if (!frame_) return; 4851cb0ef41Sopenharmony_ci 4861cb0ef41Sopenharmony_ci // Check that we have actually moved to the previous frame in the stack. 4871cb0ef41Sopenharmony_ci if (frame_->sp() <= last_sp || frame_->fp() <= last_fp) { 4881cb0ef41Sopenharmony_ci frame_ = nullptr; 4891cb0ef41Sopenharmony_ci } 4901cb0ef41Sopenharmony_ci} 4911cb0ef41Sopenharmony_ci 4921cb0ef41Sopenharmony_cibool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const { 4931cb0ef41Sopenharmony_ci return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp()); 4941cb0ef41Sopenharmony_ci} 4951cb0ef41Sopenharmony_ci 4961cb0ef41Sopenharmony_cibool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) { 4971cb0ef41Sopenharmony_ci StackFrame::State state; 4981cb0ef41Sopenharmony_ci if (frame->is_entry() || frame->is_construct_entry()) { 4991cb0ef41Sopenharmony_ci // See EntryFrame::GetCallerState. It computes the caller FP address 5001cb0ef41Sopenharmony_ci // and calls ExitFrame::GetStateForFramePointer on it. We need to be 5011cb0ef41Sopenharmony_ci // sure that caller FP address is valid. 5021cb0ef41Sopenharmony_ci Address caller_fp = 5031cb0ef41Sopenharmony_ci Memory<Address>(frame->fp() + EntryFrameConstants::kCallerFPOffset); 5041cb0ef41Sopenharmony_ci if (!IsValidExitFrame(caller_fp)) return false; 5051cb0ef41Sopenharmony_ci } 5061cb0ef41Sopenharmony_ci frame->ComputeCallerState(&state); 5071cb0ef41Sopenharmony_ci return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) && 5081cb0ef41Sopenharmony_ci SingletonFor(frame->GetCallerState(&state)) != nullptr; 5091cb0ef41Sopenharmony_ci} 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_cibool SafeStackFrameIterator::IsValidExitFrame(Address fp) const { 5121cb0ef41Sopenharmony_ci if (!IsValidStackAddress(fp)) return false; 5131cb0ef41Sopenharmony_ci Address sp = ExitFrame::ComputeStackPointer(fp); 5141cb0ef41Sopenharmony_ci if (!IsValidStackAddress(sp)) return false; 5151cb0ef41Sopenharmony_ci StackFrame::State state; 5161cb0ef41Sopenharmony_ci ExitFrame::FillState(fp, sp, &state); 5171cb0ef41Sopenharmony_ci MSAN_MEMORY_IS_INITIALIZED(state.pc_address, sizeof(state.pc_address)); 5181cb0ef41Sopenharmony_ci return *state.pc_address != kNullAddress; 5191cb0ef41Sopenharmony_ci} 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_civoid SafeStackFrameIterator::Advance() { 5221cb0ef41Sopenharmony_ci while (true) { 5231cb0ef41Sopenharmony_ci AdvanceOneFrame(); 5241cb0ef41Sopenharmony_ci if (done()) break; 5251cb0ef41Sopenharmony_ci ExternalCallbackScope* last_callback_scope = nullptr; 5261cb0ef41Sopenharmony_ci while (external_callback_scope_ != nullptr && 5271cb0ef41Sopenharmony_ci external_callback_scope_->scope_address() < frame_->fp()) { 5281cb0ef41Sopenharmony_ci // As long as the setup of a frame is not atomic, we may happen to be 5291cb0ef41Sopenharmony_ci // in an interval where an ExternalCallbackScope is already created, 5301cb0ef41Sopenharmony_ci // but the frame is not yet entered. So we are actually observing 5311cb0ef41Sopenharmony_ci // the previous frame. 5321cb0ef41Sopenharmony_ci // Skip all the ExternalCallbackScope's that are below the current fp. 5331cb0ef41Sopenharmony_ci last_callback_scope = external_callback_scope_; 5341cb0ef41Sopenharmony_ci external_callback_scope_ = external_callback_scope_->previous(); 5351cb0ef41Sopenharmony_ci } 5361cb0ef41Sopenharmony_ci if (frame_->is_java_script()) break; 5371cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 5381cb0ef41Sopenharmony_ci if (frame_->is_wasm() || frame_->is_wasm_to_js() || 5391cb0ef41Sopenharmony_ci frame_->is_js_to_wasm()) { 5401cb0ef41Sopenharmony_ci break; 5411cb0ef41Sopenharmony_ci } 5421cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 5431cb0ef41Sopenharmony_ci if (frame_->is_exit() || frame_->is_builtin_exit()) { 5441cb0ef41Sopenharmony_ci // Some of the EXIT frames may have ExternalCallbackScope allocated on 5451cb0ef41Sopenharmony_ci // top of them. In that case the scope corresponds to the first EXIT 5461cb0ef41Sopenharmony_ci // frame beneath it. There may be other EXIT frames on top of the 5471cb0ef41Sopenharmony_ci // ExternalCallbackScope, just skip them as we cannot collect any useful 5481cb0ef41Sopenharmony_ci // information about them. 5491cb0ef41Sopenharmony_ci if (last_callback_scope) { 5501cb0ef41Sopenharmony_ci frame_->state_.pc_address = 5511cb0ef41Sopenharmony_ci last_callback_scope->callback_entrypoint_address(); 5521cb0ef41Sopenharmony_ci } 5531cb0ef41Sopenharmony_ci break; 5541cb0ef41Sopenharmony_ci } 5551cb0ef41Sopenharmony_ci } 5561cb0ef41Sopenharmony_ci} 5571cb0ef41Sopenharmony_ci 5581cb0ef41Sopenharmony_ci// ------------------------------------------------------------------------- 5591cb0ef41Sopenharmony_ci 5601cb0ef41Sopenharmony_cinamespace { 5611cb0ef41Sopenharmony_ciCode GetContainingCode(Isolate* isolate, Address pc) { 5621cb0ef41Sopenharmony_ci return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code; 5631cb0ef41Sopenharmony_ci} 5641cb0ef41Sopenharmony_ci} // namespace 5651cb0ef41Sopenharmony_ci 5661cb0ef41Sopenharmony_ciCode StackFrame::LookupCode() const { 5671cb0ef41Sopenharmony_ci Code result = GetContainingCode(isolate(), pc()); 5681cb0ef41Sopenharmony_ci DCHECK_GE(pc(), result.InstructionStart(isolate(), pc())); 5691cb0ef41Sopenharmony_ci DCHECK_LT(pc(), result.InstructionEnd(isolate(), pc())); 5701cb0ef41Sopenharmony_ci return result; 5711cb0ef41Sopenharmony_ci} 5721cb0ef41Sopenharmony_ci 5731cb0ef41Sopenharmony_civoid StackFrame::IteratePc(RootVisitor* v, Address* pc_address, 5741cb0ef41Sopenharmony_ci Address* constant_pool_address, Code holder) const { 5751cb0ef41Sopenharmony_ci Address old_pc = ReadPC(pc_address); 5761cb0ef41Sopenharmony_ci DCHECK(ReadOnlyHeap::Contains(holder) || 5771cb0ef41Sopenharmony_ci holder.GetHeap()->GcSafeCodeContains(holder, old_pc)); 5781cb0ef41Sopenharmony_ci unsigned pc_offset = holder.GetOffsetFromInstructionStart(isolate_, old_pc); 5791cb0ef41Sopenharmony_ci Object code = holder; 5801cb0ef41Sopenharmony_ci v->VisitRunningCode(FullObjectSlot(&code)); 5811cb0ef41Sopenharmony_ci if (code == holder) return; 5821cb0ef41Sopenharmony_ci holder = Code::unchecked_cast(code); 5831cb0ef41Sopenharmony_ci Address pc = holder.InstructionStart(isolate_, old_pc) + pc_offset; 5841cb0ef41Sopenharmony_ci // TODO(v8:10026): avoid replacing a signed pointer. 5851cb0ef41Sopenharmony_ci PointerAuthentication::ReplacePC(pc_address, pc, kSystemPointerSize); 5861cb0ef41Sopenharmony_ci if (FLAG_enable_embedded_constant_pool && constant_pool_address) { 5871cb0ef41Sopenharmony_ci *constant_pool_address = holder.constant_pool(); 5881cb0ef41Sopenharmony_ci } 5891cb0ef41Sopenharmony_ci} 5901cb0ef41Sopenharmony_ci 5911cb0ef41Sopenharmony_civoid StackFrame::SetReturnAddressLocationResolver( 5921cb0ef41Sopenharmony_ci ReturnAddressLocationResolver resolver) { 5931cb0ef41Sopenharmony_ci DCHECK_NULL(return_address_location_resolver_); 5941cb0ef41Sopenharmony_ci return_address_location_resolver_ = resolver; 5951cb0ef41Sopenharmony_ci} 5961cb0ef41Sopenharmony_ci 5971cb0ef41Sopenharmony_ciStackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator, 5981cb0ef41Sopenharmony_ci State* state) { 5991cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 6001cb0ef41Sopenharmony_ci if (state->fp == kNullAddress) { 6011cb0ef41Sopenharmony_ci DCHECK(FLAG_experimental_wasm_stack_switching); 6021cb0ef41Sopenharmony_ci return NO_FRAME_TYPE; 6031cb0ef41Sopenharmony_ci } 6041cb0ef41Sopenharmony_ci#endif 6051cb0ef41Sopenharmony_ci 6061cb0ef41Sopenharmony_ci MSAN_MEMORY_IS_INITIALIZED( 6071cb0ef41Sopenharmony_ci state->fp + CommonFrameConstants::kContextOrFrameTypeOffset, 6081cb0ef41Sopenharmony_ci kSystemPointerSize); 6091cb0ef41Sopenharmony_ci intptr_t marker = Memory<intptr_t>( 6101cb0ef41Sopenharmony_ci state->fp + CommonFrameConstants::kContextOrFrameTypeOffset); 6111cb0ef41Sopenharmony_ci Address pc = StackFrame::ReadPC(state->pc_address); 6121cb0ef41Sopenharmony_ci if (!iterator->can_access_heap_objects_) { 6131cb0ef41Sopenharmony_ci // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really 6141cb0ef41Sopenharmony_ci // means that we are being called from the profiler, which can interrupt 6151cb0ef41Sopenharmony_ci // the VM with a signal at any arbitrary instruction, with essentially 6161cb0ef41Sopenharmony_ci // anything on the stack. So basically none of these checks are 100% 6171cb0ef41Sopenharmony_ci // reliable. 6181cb0ef41Sopenharmony_ci MSAN_MEMORY_IS_INITIALIZED( 6191cb0ef41Sopenharmony_ci state->fp + StandardFrameConstants::kFunctionOffset, 6201cb0ef41Sopenharmony_ci kSystemPointerSize); 6211cb0ef41Sopenharmony_ci Object maybe_function = Object( 6221cb0ef41Sopenharmony_ci Memory<Address>(state->fp + StandardFrameConstants::kFunctionOffset)); 6231cb0ef41Sopenharmony_ci if (!StackFrame::IsTypeMarker(marker)) { 6241cb0ef41Sopenharmony_ci if (maybe_function.IsSmi()) { 6251cb0ef41Sopenharmony_ci return NATIVE; 6261cb0ef41Sopenharmony_ci } else if (IsInterpreterFramePc(iterator->isolate(), pc, state)) { 6271cb0ef41Sopenharmony_ci return INTERPRETED; 6281cb0ef41Sopenharmony_ci } else { 6291cb0ef41Sopenharmony_ci return OPTIMIZED; 6301cb0ef41Sopenharmony_ci } 6311cb0ef41Sopenharmony_ci } 6321cb0ef41Sopenharmony_ci } else { 6331cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 6341cb0ef41Sopenharmony_ci // If the {pc} does not point into WebAssembly code we can rely on the 6351cb0ef41Sopenharmony_ci // returned {wasm_code} to be null and fall back to {GetContainingCode}. 6361cb0ef41Sopenharmony_ci wasm::WasmCodeRefScope code_ref_scope; 6371cb0ef41Sopenharmony_ci if (wasm::WasmCode* wasm_code = 6381cb0ef41Sopenharmony_ci wasm::GetWasmCodeManager()->LookupCode(pc)) { 6391cb0ef41Sopenharmony_ci switch (wasm_code->kind()) { 6401cb0ef41Sopenharmony_ci case wasm::WasmCode::kWasmFunction: 6411cb0ef41Sopenharmony_ci return WASM; 6421cb0ef41Sopenharmony_ci case wasm::WasmCode::kWasmToCapiWrapper: 6431cb0ef41Sopenharmony_ci return WASM_EXIT; 6441cb0ef41Sopenharmony_ci case wasm::WasmCode::kWasmToJsWrapper: 6451cb0ef41Sopenharmony_ci return WASM_TO_JS; 6461cb0ef41Sopenharmony_ci default: 6471cb0ef41Sopenharmony_ci UNREACHABLE(); 6481cb0ef41Sopenharmony_ci } 6491cb0ef41Sopenharmony_ci } 6501cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 6511cb0ef41Sopenharmony_ci 6521cb0ef41Sopenharmony_ci // Look up the code object to figure out the type of the stack frame. 6531cb0ef41Sopenharmony_ci Code code_obj = GetContainingCode(iterator->isolate(), pc); 6541cb0ef41Sopenharmony_ci if (!code_obj.is_null()) { 6551cb0ef41Sopenharmony_ci switch (code_obj.kind()) { 6561cb0ef41Sopenharmony_ci case CodeKind::BUILTIN: 6571cb0ef41Sopenharmony_ci if (StackFrame::IsTypeMarker(marker)) break; 6581cb0ef41Sopenharmony_ci if (code_obj.is_interpreter_trampoline_builtin() || 6591cb0ef41Sopenharmony_ci // Frames for baseline entry trampolines on the stack are still 6601cb0ef41Sopenharmony_ci // interpreted frames. 6611cb0ef41Sopenharmony_ci code_obj.is_baseline_trampoline_builtin()) { 6621cb0ef41Sopenharmony_ci return INTERPRETED; 6631cb0ef41Sopenharmony_ci } 6641cb0ef41Sopenharmony_ci if (code_obj.is_baseline_leave_frame_builtin()) { 6651cb0ef41Sopenharmony_ci return BASELINE; 6661cb0ef41Sopenharmony_ci } 6671cb0ef41Sopenharmony_ci if (code_obj.is_turbofanned()) { 6681cb0ef41Sopenharmony_ci // TODO(bmeurer): We treat frames for BUILTIN Code objects as 6691cb0ef41Sopenharmony_ci // OptimizedFrame for now (all the builtins with JavaScript 6701cb0ef41Sopenharmony_ci // linkage are actually generated with TurboFan currently, so 6711cb0ef41Sopenharmony_ci // this is sound). 6721cb0ef41Sopenharmony_ci return OPTIMIZED; 6731cb0ef41Sopenharmony_ci } 6741cb0ef41Sopenharmony_ci return BUILTIN; 6751cb0ef41Sopenharmony_ci case CodeKind::TURBOFAN: 6761cb0ef41Sopenharmony_ci case CodeKind::MAGLEV: 6771cb0ef41Sopenharmony_ci return OPTIMIZED; 6781cb0ef41Sopenharmony_ci case CodeKind::BASELINE: 6791cb0ef41Sopenharmony_ci return Type::BASELINE; 6801cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 6811cb0ef41Sopenharmony_ci case CodeKind::JS_TO_WASM_FUNCTION: 6821cb0ef41Sopenharmony_ci return JS_TO_WASM; 6831cb0ef41Sopenharmony_ci case CodeKind::JS_TO_JS_FUNCTION: 6841cb0ef41Sopenharmony_ci return STUB; 6851cb0ef41Sopenharmony_ci case CodeKind::C_WASM_ENTRY: 6861cb0ef41Sopenharmony_ci return C_WASM_ENTRY; 6871cb0ef41Sopenharmony_ci case CodeKind::WASM_TO_JS_FUNCTION: 6881cb0ef41Sopenharmony_ci return WASM_TO_JS; 6891cb0ef41Sopenharmony_ci case CodeKind::WASM_FUNCTION: 6901cb0ef41Sopenharmony_ci case CodeKind::WASM_TO_CAPI_FUNCTION: 6911cb0ef41Sopenharmony_ci // Never appear as on-heap {Code} objects. 6921cb0ef41Sopenharmony_ci UNREACHABLE(); 6931cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 6941cb0ef41Sopenharmony_ci default: 6951cb0ef41Sopenharmony_ci // All other types should have an explicit marker 6961cb0ef41Sopenharmony_ci break; 6971cb0ef41Sopenharmony_ci } 6981cb0ef41Sopenharmony_ci } else { 6991cb0ef41Sopenharmony_ci return NATIVE; 7001cb0ef41Sopenharmony_ci } 7011cb0ef41Sopenharmony_ci } 7021cb0ef41Sopenharmony_ci DCHECK(StackFrame::IsTypeMarker(marker)); 7031cb0ef41Sopenharmony_ci StackFrame::Type candidate = StackFrame::MarkerToType(marker); 7041cb0ef41Sopenharmony_ci switch (candidate) { 7051cb0ef41Sopenharmony_ci case ENTRY: 7061cb0ef41Sopenharmony_ci case CONSTRUCT_ENTRY: 7071cb0ef41Sopenharmony_ci case EXIT: 7081cb0ef41Sopenharmony_ci case BUILTIN_CONTINUATION: 7091cb0ef41Sopenharmony_ci case JAVA_SCRIPT_BUILTIN_CONTINUATION: 7101cb0ef41Sopenharmony_ci case JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH: 7111cb0ef41Sopenharmony_ci case BUILTIN_EXIT: 7121cb0ef41Sopenharmony_ci case STUB: 7131cb0ef41Sopenharmony_ci case INTERNAL: 7141cb0ef41Sopenharmony_ci case CONSTRUCT: 7151cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 7161cb0ef41Sopenharmony_ci case WASM_TO_JS: 7171cb0ef41Sopenharmony_ci case WASM: 7181cb0ef41Sopenharmony_ci case WASM_COMPILE_LAZY: 7191cb0ef41Sopenharmony_ci case WASM_EXIT: 7201cb0ef41Sopenharmony_ci case WASM_DEBUG_BREAK: 7211cb0ef41Sopenharmony_ci case JS_TO_WASM: 7221cb0ef41Sopenharmony_ci case STACK_SWITCH: 7231cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 7241cb0ef41Sopenharmony_ci return candidate; 7251cb0ef41Sopenharmony_ci case OPTIMIZED: 7261cb0ef41Sopenharmony_ci case INTERPRETED: 7271cb0ef41Sopenharmony_ci default: 7281cb0ef41Sopenharmony_ci // Unoptimized and optimized JavaScript frames, including 7291cb0ef41Sopenharmony_ci // interpreted frames, should never have a StackFrame::Type 7301cb0ef41Sopenharmony_ci // marker. If we find one, we're likely being called from the 7311cb0ef41Sopenharmony_ci // profiler in a bogus stack frame. 7321cb0ef41Sopenharmony_ci return NATIVE; 7331cb0ef41Sopenharmony_ci } 7341cb0ef41Sopenharmony_ci} 7351cb0ef41Sopenharmony_ci 7361cb0ef41Sopenharmony_ci#ifdef DEBUG 7371cb0ef41Sopenharmony_cibool StackFrame::can_access_heap_objects() const { 7381cb0ef41Sopenharmony_ci return iterator_->can_access_heap_objects_; 7391cb0ef41Sopenharmony_ci} 7401cb0ef41Sopenharmony_ci#endif 7411cb0ef41Sopenharmony_ci 7421cb0ef41Sopenharmony_ciStackFrame::Type StackFrame::GetCallerState(State* state) const { 7431cb0ef41Sopenharmony_ci ComputeCallerState(state); 7441cb0ef41Sopenharmony_ci return ComputeType(iterator_, state); 7451cb0ef41Sopenharmony_ci} 7461cb0ef41Sopenharmony_ci 7471cb0ef41Sopenharmony_ciAddress CommonFrame::GetCallerStackPointer() const { 7481cb0ef41Sopenharmony_ci return fp() + CommonFrameConstants::kCallerSPOffset; 7491cb0ef41Sopenharmony_ci} 7501cb0ef41Sopenharmony_ci 7511cb0ef41Sopenharmony_civoid NativeFrame::ComputeCallerState(State* state) const { 7521cb0ef41Sopenharmony_ci state->sp = caller_sp(); 7531cb0ef41Sopenharmony_ci state->fp = Memory<Address>(fp() + CommonFrameConstants::kCallerFPOffset); 7541cb0ef41Sopenharmony_ci state->pc_address = ResolveReturnAddressLocation( 7551cb0ef41Sopenharmony_ci reinterpret_cast<Address*>(fp() + CommonFrameConstants::kCallerPCOffset)); 7561cb0ef41Sopenharmony_ci state->callee_pc_address = nullptr; 7571cb0ef41Sopenharmony_ci state->constant_pool_address = nullptr; 7581cb0ef41Sopenharmony_ci} 7591cb0ef41Sopenharmony_ci 7601cb0ef41Sopenharmony_ciCode EntryFrame::unchecked_code() const { 7611cb0ef41Sopenharmony_ci return FromCodeT(isolate()->builtins()->code(Builtin::kJSEntry)); 7621cb0ef41Sopenharmony_ci} 7631cb0ef41Sopenharmony_ci 7641cb0ef41Sopenharmony_civoid EntryFrame::ComputeCallerState(State* state) const { 7651cb0ef41Sopenharmony_ci GetCallerState(state); 7661cb0ef41Sopenharmony_ci} 7671cb0ef41Sopenharmony_ci 7681cb0ef41Sopenharmony_ciStackFrame::Type EntryFrame::GetCallerState(State* state) const { 7691cb0ef41Sopenharmony_ci const int offset = EntryFrameConstants::kCallerFPOffset; 7701cb0ef41Sopenharmony_ci Address fp = Memory<Address>(this->fp() + offset); 7711cb0ef41Sopenharmony_ci return ExitFrame::GetStateForFramePointer(fp, state); 7721cb0ef41Sopenharmony_ci} 7731cb0ef41Sopenharmony_ci 7741cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 7751cb0ef41Sopenharmony_ciStackFrame::Type CWasmEntryFrame::GetCallerState(State* state) const { 7761cb0ef41Sopenharmony_ci const int offset = CWasmEntryFrameConstants::kCEntryFPOffset; 7771cb0ef41Sopenharmony_ci Address fp = Memory<Address>(this->fp() + offset); 7781cb0ef41Sopenharmony_ci return ExitFrame::GetStateForFramePointer(fp, state); 7791cb0ef41Sopenharmony_ci} 7801cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 7811cb0ef41Sopenharmony_ci 7821cb0ef41Sopenharmony_ciCode ConstructEntryFrame::unchecked_code() const { 7831cb0ef41Sopenharmony_ci return FromCodeT(isolate()->builtins()->code(Builtin::kJSConstructEntry)); 7841cb0ef41Sopenharmony_ci} 7851cb0ef41Sopenharmony_ci 7861cb0ef41Sopenharmony_civoid ExitFrame::ComputeCallerState(State* state) const { 7871cb0ef41Sopenharmony_ci // Set up the caller state. 7881cb0ef41Sopenharmony_ci state->sp = caller_sp(); 7891cb0ef41Sopenharmony_ci state->fp = Memory<Address>(fp() + ExitFrameConstants::kCallerFPOffset); 7901cb0ef41Sopenharmony_ci state->pc_address = ResolveReturnAddressLocation( 7911cb0ef41Sopenharmony_ci reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset)); 7921cb0ef41Sopenharmony_ci state->callee_pc_address = nullptr; 7931cb0ef41Sopenharmony_ci if (FLAG_enable_embedded_constant_pool) { 7941cb0ef41Sopenharmony_ci state->constant_pool_address = reinterpret_cast<Address*>( 7951cb0ef41Sopenharmony_ci fp() + ExitFrameConstants::kConstantPoolOffset); 7961cb0ef41Sopenharmony_ci } 7971cb0ef41Sopenharmony_ci} 7981cb0ef41Sopenharmony_ci 7991cb0ef41Sopenharmony_civoid ExitFrame::Iterate(RootVisitor* v) const { 8001cb0ef41Sopenharmony_ci // The arguments are traversed as part of the expression stack of 8011cb0ef41Sopenharmony_ci // the calling frame. 8021cb0ef41Sopenharmony_ci IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 8031cb0ef41Sopenharmony_ci} 8041cb0ef41Sopenharmony_ci 8051cb0ef41Sopenharmony_ciStackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) { 8061cb0ef41Sopenharmony_ci if (fp == 0) return NO_FRAME_TYPE; 8071cb0ef41Sopenharmony_ci StackFrame::Type type = ComputeFrameType(fp); 8081cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 8091cb0ef41Sopenharmony_ci Address sp = type == WASM_EXIT ? WasmExitFrame::ComputeStackPointer(fp) 8101cb0ef41Sopenharmony_ci : ExitFrame::ComputeStackPointer(fp); 8111cb0ef41Sopenharmony_ci#else 8121cb0ef41Sopenharmony_ci Address sp = ExitFrame::ComputeStackPointer(fp); 8131cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 8141cb0ef41Sopenharmony_ci FillState(fp, sp, state); 8151cb0ef41Sopenharmony_ci DCHECK_NE(*state->pc_address, kNullAddress); 8161cb0ef41Sopenharmony_ci return type; 8171cb0ef41Sopenharmony_ci} 8181cb0ef41Sopenharmony_ci 8191cb0ef41Sopenharmony_ciStackFrame::Type ExitFrame::ComputeFrameType(Address fp) { 8201cb0ef41Sopenharmony_ci // Distinguish between between regular and builtin exit frames. 8211cb0ef41Sopenharmony_ci // Default to EXIT in all hairy cases (e.g., when called from profiler). 8221cb0ef41Sopenharmony_ci const int offset = ExitFrameConstants::kFrameTypeOffset; 8231cb0ef41Sopenharmony_ci Object marker(Memory<Address>(fp + offset)); 8241cb0ef41Sopenharmony_ci 8251cb0ef41Sopenharmony_ci if (!marker.IsSmi()) { 8261cb0ef41Sopenharmony_ci return EXIT; 8271cb0ef41Sopenharmony_ci } 8281cb0ef41Sopenharmony_ci 8291cb0ef41Sopenharmony_ci intptr_t marker_int = bit_cast<intptr_t>(marker); 8301cb0ef41Sopenharmony_ci 8311cb0ef41Sopenharmony_ci StackFrame::Type frame_type = static_cast<StackFrame::Type>(marker_int >> 1); 8321cb0ef41Sopenharmony_ci switch (frame_type) { 8331cb0ef41Sopenharmony_ci case BUILTIN_EXIT: 8341cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 8351cb0ef41Sopenharmony_ci case WASM_EXIT: 8361cb0ef41Sopenharmony_ci case STACK_SWITCH: 8371cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 8381cb0ef41Sopenharmony_ci return frame_type; 8391cb0ef41Sopenharmony_ci default: 8401cb0ef41Sopenharmony_ci return EXIT; 8411cb0ef41Sopenharmony_ci } 8421cb0ef41Sopenharmony_ci} 8431cb0ef41Sopenharmony_ci 8441cb0ef41Sopenharmony_ciAddress ExitFrame::ComputeStackPointer(Address fp) { 8451cb0ef41Sopenharmony_ci MSAN_MEMORY_IS_INITIALIZED(fp + ExitFrameConstants::kSPOffset, 8461cb0ef41Sopenharmony_ci kSystemPointerSize); 8471cb0ef41Sopenharmony_ci return Memory<Address>(fp + ExitFrameConstants::kSPOffset); 8481cb0ef41Sopenharmony_ci} 8491cb0ef41Sopenharmony_ci 8501cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 8511cb0ef41Sopenharmony_ciAddress WasmExitFrame::ComputeStackPointer(Address fp) { 8521cb0ef41Sopenharmony_ci // For WASM_EXIT frames, {sp} is only needed for finding the PC slot, 8531cb0ef41Sopenharmony_ci // everything else is handled via safepoint information. 8541cb0ef41Sopenharmony_ci Address sp = fp + WasmExitFrameConstants::kWasmInstanceOffset; 8551cb0ef41Sopenharmony_ci DCHECK_EQ(sp - 1 * kPCOnStackSize, 8561cb0ef41Sopenharmony_ci fp + WasmExitFrameConstants::kCallingPCOffset); 8571cb0ef41Sopenharmony_ci return sp; 8581cb0ef41Sopenharmony_ci} 8591cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 8601cb0ef41Sopenharmony_ci 8611cb0ef41Sopenharmony_civoid ExitFrame::FillState(Address fp, Address sp, State* state) { 8621cb0ef41Sopenharmony_ci state->sp = sp; 8631cb0ef41Sopenharmony_ci state->fp = fp; 8641cb0ef41Sopenharmony_ci state->pc_address = ResolveReturnAddressLocation( 8651cb0ef41Sopenharmony_ci reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize)); 8661cb0ef41Sopenharmony_ci state->callee_pc_address = nullptr; 8671cb0ef41Sopenharmony_ci // The constant pool recorded in the exit frame is not associated 8681cb0ef41Sopenharmony_ci // with the pc in this state (the return address into a C entry 8691cb0ef41Sopenharmony_ci // stub). ComputeCallerState will retrieve the constant pool 8701cb0ef41Sopenharmony_ci // together with the associated caller pc. 8711cb0ef41Sopenharmony_ci state->constant_pool_address = nullptr; 8721cb0ef41Sopenharmony_ci} 8731cb0ef41Sopenharmony_ci 8741cb0ef41Sopenharmony_civoid BuiltinExitFrame::Summarize(std::vector<FrameSummary>* frames) const { 8751cb0ef41Sopenharmony_ci DCHECK(frames->empty()); 8761cb0ef41Sopenharmony_ci Handle<FixedArray> parameters = GetParameters(); 8771cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 8781cb0ef41Sopenharmony_ci Code code = LookupCode(); 8791cb0ef41Sopenharmony_ci int code_offset = code.GetOffsetFromInstructionStart(isolate(), pc()); 8801cb0ef41Sopenharmony_ci FrameSummary::JavaScriptFrameSummary summary( 8811cb0ef41Sopenharmony_ci isolate(), receiver(), function(), AbstractCode::cast(code), code_offset, 8821cb0ef41Sopenharmony_ci IsConstructor(), *parameters); 8831cb0ef41Sopenharmony_ci frames->push_back(summary); 8841cb0ef41Sopenharmony_ci} 8851cb0ef41Sopenharmony_ci 8861cb0ef41Sopenharmony_ciJSFunction BuiltinExitFrame::function() const { 8871cb0ef41Sopenharmony_ci return JSFunction::cast(target_slot_object()); 8881cb0ef41Sopenharmony_ci} 8891cb0ef41Sopenharmony_ci 8901cb0ef41Sopenharmony_ciObject BuiltinExitFrame::receiver() const { return receiver_slot_object(); } 8911cb0ef41Sopenharmony_ci 8921cb0ef41Sopenharmony_ciObject BuiltinExitFrame::GetParameter(int i) const { 8931cb0ef41Sopenharmony_ci DCHECK(i >= 0 && i < ComputeParametersCount()); 8941cb0ef41Sopenharmony_ci int offset = 8951cb0ef41Sopenharmony_ci BuiltinExitFrameConstants::kFirstArgumentOffset + i * kSystemPointerSize; 8961cb0ef41Sopenharmony_ci return Object(Memory<Address>(fp() + offset)); 8971cb0ef41Sopenharmony_ci} 8981cb0ef41Sopenharmony_ci 8991cb0ef41Sopenharmony_ciint BuiltinExitFrame::ComputeParametersCount() const { 9001cb0ef41Sopenharmony_ci Object argc_slot = argc_slot_object(); 9011cb0ef41Sopenharmony_ci DCHECK(argc_slot.IsSmi()); 9021cb0ef41Sopenharmony_ci // Argc also counts the receiver, target, new target, and argc itself as args, 9031cb0ef41Sopenharmony_ci // therefore the real argument count is argc - 4. 9041cb0ef41Sopenharmony_ci int argc = Smi::ToInt(argc_slot) - 4; 9051cb0ef41Sopenharmony_ci DCHECK_GE(argc, 0); 9061cb0ef41Sopenharmony_ci return argc; 9071cb0ef41Sopenharmony_ci} 9081cb0ef41Sopenharmony_ci 9091cb0ef41Sopenharmony_ciHandle<FixedArray> BuiltinExitFrame::GetParameters() const { 9101cb0ef41Sopenharmony_ci if (V8_LIKELY(!FLAG_detailed_error_stack_trace)) { 9111cb0ef41Sopenharmony_ci return isolate()->factory()->empty_fixed_array(); 9121cb0ef41Sopenharmony_ci } 9131cb0ef41Sopenharmony_ci int param_count = ComputeParametersCount(); 9141cb0ef41Sopenharmony_ci auto parameters = isolate()->factory()->NewFixedArray(param_count); 9151cb0ef41Sopenharmony_ci for (int i = 0; i < param_count; i++) { 9161cb0ef41Sopenharmony_ci parameters->set(i, GetParameter(i)); 9171cb0ef41Sopenharmony_ci } 9181cb0ef41Sopenharmony_ci return parameters; 9191cb0ef41Sopenharmony_ci} 9201cb0ef41Sopenharmony_ci 9211cb0ef41Sopenharmony_cibool BuiltinExitFrame::IsConstructor() const { 9221cb0ef41Sopenharmony_ci return !new_target_slot_object().IsUndefined(isolate()); 9231cb0ef41Sopenharmony_ci} 9241cb0ef41Sopenharmony_ci 9251cb0ef41Sopenharmony_cinamespace { 9261cb0ef41Sopenharmony_civoid PrintIndex(StringStream* accumulator, StackFrame::PrintMode mode, 9271cb0ef41Sopenharmony_ci int index) { 9281cb0ef41Sopenharmony_ci accumulator->Add((mode == StackFrame::OVERVIEW) ? "%5d: " : "[%d]: ", index); 9291cb0ef41Sopenharmony_ci} 9301cb0ef41Sopenharmony_ci 9311cb0ef41Sopenharmony_ciconst char* StringForStackFrameType(StackFrame::Type type) { 9321cb0ef41Sopenharmony_ci switch (type) { 9331cb0ef41Sopenharmony_ci#define CASE(value, name) \ 9341cb0ef41Sopenharmony_ci case StackFrame::value: \ 9351cb0ef41Sopenharmony_ci return #name; 9361cb0ef41Sopenharmony_ci STACK_FRAME_TYPE_LIST(CASE) 9371cb0ef41Sopenharmony_ci#undef CASE 9381cb0ef41Sopenharmony_ci default: 9391cb0ef41Sopenharmony_ci UNREACHABLE(); 9401cb0ef41Sopenharmony_ci } 9411cb0ef41Sopenharmony_ci} 9421cb0ef41Sopenharmony_ci} // namespace 9431cb0ef41Sopenharmony_ci 9441cb0ef41Sopenharmony_civoid StackFrame::Print(StringStream* accumulator, PrintMode mode, 9451cb0ef41Sopenharmony_ci int index) const { 9461cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 9471cb0ef41Sopenharmony_ci PrintIndex(accumulator, mode, index); 9481cb0ef41Sopenharmony_ci accumulator->Add(StringForStackFrameType(type())); 9491cb0ef41Sopenharmony_ci accumulator->Add(" [pc: %p]\n", reinterpret_cast<void*>(pc())); 9501cb0ef41Sopenharmony_ci} 9511cb0ef41Sopenharmony_ci 9521cb0ef41Sopenharmony_civoid BuiltinExitFrame::Print(StringStream* accumulator, PrintMode mode, 9531cb0ef41Sopenharmony_ci int index) const { 9541cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 9551cb0ef41Sopenharmony_ci Object receiver = this->receiver(); 9561cb0ef41Sopenharmony_ci JSFunction function = this->function(); 9571cb0ef41Sopenharmony_ci 9581cb0ef41Sopenharmony_ci accumulator->PrintSecurityTokenIfChanged(function); 9591cb0ef41Sopenharmony_ci PrintIndex(accumulator, mode, index); 9601cb0ef41Sopenharmony_ci accumulator->Add("builtin exit frame: "); 9611cb0ef41Sopenharmony_ci Code code; 9621cb0ef41Sopenharmony_ci if (IsConstructor()) accumulator->Add("new "); 9631cb0ef41Sopenharmony_ci accumulator->PrintFunction(function, receiver, &code); 9641cb0ef41Sopenharmony_ci 9651cb0ef41Sopenharmony_ci accumulator->Add("(this=%o", receiver); 9661cb0ef41Sopenharmony_ci 9671cb0ef41Sopenharmony_ci // Print the parameters. 9681cb0ef41Sopenharmony_ci int parameters_count = ComputeParametersCount(); 9691cb0ef41Sopenharmony_ci for (int i = 0; i < parameters_count; i++) { 9701cb0ef41Sopenharmony_ci accumulator->Add(",%o", GetParameter(i)); 9711cb0ef41Sopenharmony_ci } 9721cb0ef41Sopenharmony_ci 9731cb0ef41Sopenharmony_ci accumulator->Add(")\n\n"); 9741cb0ef41Sopenharmony_ci} 9751cb0ef41Sopenharmony_ci 9761cb0ef41Sopenharmony_ciAddress CommonFrame::GetExpressionAddress(int n) const { 9771cb0ef41Sopenharmony_ci const int offset = StandardFrameConstants::kExpressionsOffset; 9781cb0ef41Sopenharmony_ci return fp() + offset - n * kSystemPointerSize; 9791cb0ef41Sopenharmony_ci} 9801cb0ef41Sopenharmony_ci 9811cb0ef41Sopenharmony_ciAddress UnoptimizedFrame::GetExpressionAddress(int n) const { 9821cb0ef41Sopenharmony_ci const int offset = UnoptimizedFrameConstants::kExpressionsOffset; 9831cb0ef41Sopenharmony_ci return fp() + offset - n * kSystemPointerSize; 9841cb0ef41Sopenharmony_ci} 9851cb0ef41Sopenharmony_ci 9861cb0ef41Sopenharmony_ciObject CommonFrame::context() const { 9871cb0ef41Sopenharmony_ci return ReadOnlyRoots(isolate()).undefined_value(); 9881cb0ef41Sopenharmony_ci} 9891cb0ef41Sopenharmony_ci 9901cb0ef41Sopenharmony_ciint CommonFrame::position() const { 9911cb0ef41Sopenharmony_ci Code code = LookupCode(); 9921cb0ef41Sopenharmony_ci int code_offset = code.GetOffsetFromInstructionStart(isolate(), pc()); 9931cb0ef41Sopenharmony_ci return AbstractCode::cast(code).SourcePosition(code_offset); 9941cb0ef41Sopenharmony_ci} 9951cb0ef41Sopenharmony_ci 9961cb0ef41Sopenharmony_ciint CommonFrame::ComputeExpressionsCount() const { 9971cb0ef41Sopenharmony_ci Address base = GetExpressionAddress(0); 9981cb0ef41Sopenharmony_ci Address limit = sp() - kSystemPointerSize; 9991cb0ef41Sopenharmony_ci DCHECK(base >= limit); // stack grows downwards 10001cb0ef41Sopenharmony_ci // Include register-allocated locals in number of expressions. 10011cb0ef41Sopenharmony_ci return static_cast<int>((base - limit) / kSystemPointerSize); 10021cb0ef41Sopenharmony_ci} 10031cb0ef41Sopenharmony_ci 10041cb0ef41Sopenharmony_civoid CommonFrame::ComputeCallerState(State* state) const { 10051cb0ef41Sopenharmony_ci state->fp = caller_fp(); 10061cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 10071cb0ef41Sopenharmony_ci if (state->fp == kNullAddress) { 10081cb0ef41Sopenharmony_ci // An empty FP signals the first frame of a stack segment. The caller is 10091cb0ef41Sopenharmony_ci // on a different stack, or is unbound (suspended stack). 10101cb0ef41Sopenharmony_ci DCHECK(FLAG_experimental_wasm_stack_switching); 10111cb0ef41Sopenharmony_ci return; 10121cb0ef41Sopenharmony_ci } 10131cb0ef41Sopenharmony_ci#endif 10141cb0ef41Sopenharmony_ci state->sp = caller_sp(); 10151cb0ef41Sopenharmony_ci state->pc_address = ResolveReturnAddressLocation( 10161cb0ef41Sopenharmony_ci reinterpret_cast<Address*>(ComputePCAddress(fp()))); 10171cb0ef41Sopenharmony_ci state->callee_fp = fp(); 10181cb0ef41Sopenharmony_ci state->callee_pc_address = pc_address(); 10191cb0ef41Sopenharmony_ci state->constant_pool_address = 10201cb0ef41Sopenharmony_ci reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp())); 10211cb0ef41Sopenharmony_ci} 10221cb0ef41Sopenharmony_ci 10231cb0ef41Sopenharmony_civoid CommonFrame::Summarize(std::vector<FrameSummary>* functions) const { 10241cb0ef41Sopenharmony_ci // This should only be called on frames which override this method. 10251cb0ef41Sopenharmony_ci UNREACHABLE(); 10261cb0ef41Sopenharmony_ci} 10271cb0ef41Sopenharmony_ci 10281cb0ef41Sopenharmony_civoid CommonFrame::IterateCompiledFrame(RootVisitor* v) const { 10291cb0ef41Sopenharmony_ci // Make sure that we're not doing "safe" stack frame iteration. We cannot 10301cb0ef41Sopenharmony_ci // possibly find pointers in optimized frames in that state. 10311cb0ef41Sopenharmony_ci DCHECK(can_access_heap_objects()); 10321cb0ef41Sopenharmony_ci 10331cb0ef41Sopenharmony_ci // Find the code and compute the safepoint information. 10341cb0ef41Sopenharmony_ci Address inner_pointer = pc(); 10351cb0ef41Sopenharmony_ci SafepointEntry safepoint_entry; 10361cb0ef41Sopenharmony_ci uint32_t stack_slots = 0; 10371cb0ef41Sopenharmony_ci Code code; 10381cb0ef41Sopenharmony_ci bool has_tagged_outgoing_params = false; 10391cb0ef41Sopenharmony_ci uint16_t first_tagged_parameter_slot = 0; 10401cb0ef41Sopenharmony_ci uint16_t num_tagged_parameter_slots = 0; 10411cb0ef41Sopenharmony_ci bool is_wasm = false; 10421cb0ef41Sopenharmony_ci 10431cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 10441cb0ef41Sopenharmony_ci bool has_wasm_feedback_slot = false; 10451cb0ef41Sopenharmony_ci if (auto* wasm_code = wasm::GetWasmCodeManager()->LookupCode(inner_pointer)) { 10461cb0ef41Sopenharmony_ci is_wasm = true; 10471cb0ef41Sopenharmony_ci SafepointTable table(wasm_code); 10481cb0ef41Sopenharmony_ci safepoint_entry = table.FindEntry(inner_pointer); 10491cb0ef41Sopenharmony_ci stack_slots = wasm_code->stack_slots(); 10501cb0ef41Sopenharmony_ci has_tagged_outgoing_params = 10511cb0ef41Sopenharmony_ci wasm_code->kind() != wasm::WasmCode::kWasmFunction && 10521cb0ef41Sopenharmony_ci wasm_code->kind() != wasm::WasmCode::kWasmToCapiWrapper; 10531cb0ef41Sopenharmony_ci first_tagged_parameter_slot = wasm_code->first_tagged_parameter_slot(); 10541cb0ef41Sopenharmony_ci num_tagged_parameter_slots = wasm_code->num_tagged_parameter_slots(); 10551cb0ef41Sopenharmony_ci if (wasm_code->is_liftoff() && FLAG_wasm_speculative_inlining) { 10561cb0ef41Sopenharmony_ci has_wasm_feedback_slot = true; 10571cb0ef41Sopenharmony_ci } 10581cb0ef41Sopenharmony_ci } 10591cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 10601cb0ef41Sopenharmony_ci 10611cb0ef41Sopenharmony_ci if (!is_wasm) { 10621cb0ef41Sopenharmony_ci InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry = 10631cb0ef41Sopenharmony_ci isolate()->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer); 10641cb0ef41Sopenharmony_ci if (!entry->safepoint_entry.is_initialized()) { 10651cb0ef41Sopenharmony_ci entry->safepoint_entry = 10661cb0ef41Sopenharmony_ci entry->code.GetSafepointEntry(isolate(), inner_pointer); 10671cb0ef41Sopenharmony_ci DCHECK(entry->safepoint_entry.is_initialized()); 10681cb0ef41Sopenharmony_ci } else { 10691cb0ef41Sopenharmony_ci DCHECK_EQ(entry->safepoint_entry, 10701cb0ef41Sopenharmony_ci entry->code.GetSafepointEntry(isolate(), inner_pointer)); 10711cb0ef41Sopenharmony_ci } 10721cb0ef41Sopenharmony_ci 10731cb0ef41Sopenharmony_ci code = entry->code; 10741cb0ef41Sopenharmony_ci safepoint_entry = entry->safepoint_entry; 10751cb0ef41Sopenharmony_ci stack_slots = code.stack_slots(); 10761cb0ef41Sopenharmony_ci 10771cb0ef41Sopenharmony_ci has_tagged_outgoing_params = code.has_tagged_outgoing_params(); 10781cb0ef41Sopenharmony_ci 10791cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 10801cb0ef41Sopenharmony_ci // With inlined JS-to-Wasm calls, we can be in an OptimizedFrame and 10811cb0ef41Sopenharmony_ci // directly call a Wasm function from JavaScript. In this case the 10821cb0ef41Sopenharmony_ci // parameters we pass to the callee are not tagged. 10831cb0ef41Sopenharmony_ci wasm::WasmCode* wasm_callee = 10841cb0ef41Sopenharmony_ci wasm::GetWasmCodeManager()->LookupCode(callee_pc()); 10851cb0ef41Sopenharmony_ci bool is_wasm_call = (wasm_callee != nullptr); 10861cb0ef41Sopenharmony_ci if (is_wasm_call) has_tagged_outgoing_params = false; 10871cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 10881cb0ef41Sopenharmony_ci } 10891cb0ef41Sopenharmony_ci 10901cb0ef41Sopenharmony_ci // Determine the fixed header and spill slot area size. 10911cb0ef41Sopenharmony_ci int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp; 10921cb0ef41Sopenharmony_ci intptr_t marker = 10931cb0ef41Sopenharmony_ci Memory<intptr_t>(fp() + CommonFrameConstants::kContextOrFrameTypeOffset); 10941cb0ef41Sopenharmony_ci bool typed_frame = StackFrame::IsTypeMarker(marker); 10951cb0ef41Sopenharmony_ci if (typed_frame) { 10961cb0ef41Sopenharmony_ci StackFrame::Type candidate = StackFrame::MarkerToType(marker); 10971cb0ef41Sopenharmony_ci switch (candidate) { 10981cb0ef41Sopenharmony_ci case ENTRY: 10991cb0ef41Sopenharmony_ci case CONSTRUCT_ENTRY: 11001cb0ef41Sopenharmony_ci case EXIT: 11011cb0ef41Sopenharmony_ci case BUILTIN_CONTINUATION: 11021cb0ef41Sopenharmony_ci case JAVA_SCRIPT_BUILTIN_CONTINUATION: 11031cb0ef41Sopenharmony_ci case JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH: 11041cb0ef41Sopenharmony_ci case BUILTIN_EXIT: 11051cb0ef41Sopenharmony_ci case STUB: 11061cb0ef41Sopenharmony_ci case INTERNAL: 11071cb0ef41Sopenharmony_ci case CONSTRUCT: 11081cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 11091cb0ef41Sopenharmony_ci case JS_TO_WASM: 11101cb0ef41Sopenharmony_ci case STACK_SWITCH: 11111cb0ef41Sopenharmony_ci case C_WASM_ENTRY: 11121cb0ef41Sopenharmony_ci case WASM_DEBUG_BREAK: 11131cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 11141cb0ef41Sopenharmony_ci frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp; 11151cb0ef41Sopenharmony_ci break; 11161cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 11171cb0ef41Sopenharmony_ci case WASM_TO_JS: 11181cb0ef41Sopenharmony_ci case WASM: 11191cb0ef41Sopenharmony_ci case WASM_COMPILE_LAZY: 11201cb0ef41Sopenharmony_ci frame_header_size = WasmFrameConstants::kFixedFrameSizeFromFp; 11211cb0ef41Sopenharmony_ci if (has_wasm_feedback_slot) frame_header_size += kSystemPointerSize; 11221cb0ef41Sopenharmony_ci break; 11231cb0ef41Sopenharmony_ci case WASM_EXIT: 11241cb0ef41Sopenharmony_ci // The last value in the frame header is the calling PC, which should 11251cb0ef41Sopenharmony_ci // not be visited. 11261cb0ef41Sopenharmony_ci static_assert(WasmExitFrameConstants::kFixedSlotCountFromFp == 11271cb0ef41Sopenharmony_ci WasmFrameConstants::kFixedSlotCountFromFp + 1, 11281cb0ef41Sopenharmony_ci "WasmExitFrame has one slot more than WasmFrame"); 11291cb0ef41Sopenharmony_ci frame_header_size = WasmFrameConstants::kFixedFrameSizeFromFp; 11301cb0ef41Sopenharmony_ci break; 11311cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 11321cb0ef41Sopenharmony_ci case OPTIMIZED: 11331cb0ef41Sopenharmony_ci case INTERPRETED: 11341cb0ef41Sopenharmony_ci case BASELINE: 11351cb0ef41Sopenharmony_ci case BUILTIN: 11361cb0ef41Sopenharmony_ci // These frame types have a context, but they are actually stored 11371cb0ef41Sopenharmony_ci // in the place on the stack that one finds the frame type. 11381cb0ef41Sopenharmony_ci UNREACHABLE(); 11391cb0ef41Sopenharmony_ci case NATIVE: 11401cb0ef41Sopenharmony_ci case NO_FRAME_TYPE: 11411cb0ef41Sopenharmony_ci case NUMBER_OF_TYPES: 11421cb0ef41Sopenharmony_ci case MANUAL: 11431cb0ef41Sopenharmony_ci UNREACHABLE(); 11441cb0ef41Sopenharmony_ci } 11451cb0ef41Sopenharmony_ci } 11461cb0ef41Sopenharmony_ci 11471cb0ef41Sopenharmony_ci // slot_space holds the actual number of spill slots, without fixed frame 11481cb0ef41Sopenharmony_ci // slots. 11491cb0ef41Sopenharmony_ci const uint32_t slot_space = 11501cb0ef41Sopenharmony_ci stack_slots * kSystemPointerSize - 11511cb0ef41Sopenharmony_ci (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp); 11521cb0ef41Sopenharmony_ci 11531cb0ef41Sopenharmony_ci // base <= limit. 11541cb0ef41Sopenharmony_ci // Fixed frame slots. 11551cb0ef41Sopenharmony_ci FullObjectSlot frame_header_base(&Memory<Address>(fp() - frame_header_size)); 11561cb0ef41Sopenharmony_ci FullObjectSlot frame_header_limit( 11571cb0ef41Sopenharmony_ci &Memory<Address>(fp() - StandardFrameConstants::kCPSlotSize)); 11581cb0ef41Sopenharmony_ci // Parameters passed to the callee. 11591cb0ef41Sopenharmony_ci FullObjectSlot parameters_base(&Memory<Address>(sp())); 11601cb0ef41Sopenharmony_ci FullObjectSlot parameters_limit(frame_header_base.address() - slot_space); 11611cb0ef41Sopenharmony_ci // Spill slots are in the region ]frame_header_base, parameters_limit]; 11621cb0ef41Sopenharmony_ci 11631cb0ef41Sopenharmony_ci // Visit the rest of the parameters if they are tagged. 11641cb0ef41Sopenharmony_ci if (has_tagged_outgoing_params) { 11651cb0ef41Sopenharmony_ci v->VisitRootPointers(Root::kStackRoots, nullptr, parameters_base, 11661cb0ef41Sopenharmony_ci parameters_limit); 11671cb0ef41Sopenharmony_ci } 11681cb0ef41Sopenharmony_ci 11691cb0ef41Sopenharmony_ci // Visit pointer spill slots and locals. 11701cb0ef41Sopenharmony_ci DCHECK_GE((stack_slots + kBitsPerByte) / kBitsPerByte, 11711cb0ef41Sopenharmony_ci safepoint_entry.tagged_slots().size()); 11721cb0ef41Sopenharmony_ci int slot_offset = 0; 11731cb0ef41Sopenharmony_ci PtrComprCageBase cage_base(isolate()); 11741cb0ef41Sopenharmony_ci for (uint8_t bits : safepoint_entry.tagged_slots()) { 11751cb0ef41Sopenharmony_ci while (bits) { 11761cb0ef41Sopenharmony_ci const int bit = base::bits::CountTrailingZeros(bits); 11771cb0ef41Sopenharmony_ci bits &= ~(1 << bit); 11781cb0ef41Sopenharmony_ci FullObjectSlot spill_slot = parameters_limit + slot_offset + bit; 11791cb0ef41Sopenharmony_ci#ifdef V8_COMPRESS_POINTERS 11801cb0ef41Sopenharmony_ci // Spill slots may contain compressed values in which case the upper 11811cb0ef41Sopenharmony_ci // 32-bits will contain zeros. In order to simplify handling of such 11821cb0ef41Sopenharmony_ci // slots in GC we ensure that the slot always contains full value. 11831cb0ef41Sopenharmony_ci 11841cb0ef41Sopenharmony_ci // The spill slot may actually contain weak references so we load/store 11851cb0ef41Sopenharmony_ci // values using spill_slot.location() in order to avoid dealing with 11861cb0ef41Sopenharmony_ci // FullMaybeObjectSlots here. 11871cb0ef41Sopenharmony_ci if (V8_EXTERNAL_CODE_SPACE_BOOL) { 11881cb0ef41Sopenharmony_ci // When external code space is enabled the spill slot could contain both 11891cb0ef41Sopenharmony_ci // Code and non-Code references, which have different cage bases. So 11901cb0ef41Sopenharmony_ci // unconditional decompression of the value might corrupt Code pointers. 11911cb0ef41Sopenharmony_ci // However, given that 11921cb0ef41Sopenharmony_ci // 1) the Code pointers are never compressed by design (because 11931cb0ef41Sopenharmony_ci // otherwise we wouldn't know which cage base to apply for 11941cb0ef41Sopenharmony_ci // decompression, see respective DCHECKs in 11951cb0ef41Sopenharmony_ci // RelocInfo::target_object()), 11961cb0ef41Sopenharmony_ci // 2) there's no need to update the upper part of the full pointer 11971cb0ef41Sopenharmony_ci // because if it was there then it'll stay the same, 11981cb0ef41Sopenharmony_ci // we can avoid updating upper part of the spill slot if it already 11991cb0ef41Sopenharmony_ci // contains full value. 12001cb0ef41Sopenharmony_ci // TODO(v8:11880): Remove this special handling by enforcing builtins 12011cb0ef41Sopenharmony_ci // to use CodeTs instead of Code objects. 12021cb0ef41Sopenharmony_ci Address value = *spill_slot.location(); 12031cb0ef41Sopenharmony_ci if (!HAS_SMI_TAG(value) && value <= 0xffffffff) { 12041cb0ef41Sopenharmony_ci // We don't need to update smi values or full pointers. 12051cb0ef41Sopenharmony_ci *spill_slot.location() = 12061cb0ef41Sopenharmony_ci DecompressTaggedPointer(cage_base, static_cast<Tagged_t>(value)); 12071cb0ef41Sopenharmony_ci if (DEBUG_BOOL) { 12081cb0ef41Sopenharmony_ci // Ensure that the spill slot contains correct heap object. 12091cb0ef41Sopenharmony_ci HeapObject raw = HeapObject::cast(Object(*spill_slot.location())); 12101cb0ef41Sopenharmony_ci MapWord map_word = raw.map_word(cage_base, kRelaxedLoad); 12111cb0ef41Sopenharmony_ci HeapObject forwarded = map_word.IsForwardingAddress() 12121cb0ef41Sopenharmony_ci ? map_word.ToForwardingAddress() 12131cb0ef41Sopenharmony_ci : raw; 12141cb0ef41Sopenharmony_ci bool is_self_forwarded = 12151cb0ef41Sopenharmony_ci forwarded.map_word(cage_base, kRelaxedLoad).ptr() == 12161cb0ef41Sopenharmony_ci forwarded.address(); 12171cb0ef41Sopenharmony_ci if (is_self_forwarded) { 12181cb0ef41Sopenharmony_ci // The object might be in a self-forwarding state if it's located 12191cb0ef41Sopenharmony_ci // in new large object space. GC will fix this at a later stage. 12201cb0ef41Sopenharmony_ci CHECK(BasicMemoryChunk::FromHeapObject(forwarded) 12211cb0ef41Sopenharmony_ci ->InNewLargeObjectSpace()); 12221cb0ef41Sopenharmony_ci } else { 12231cb0ef41Sopenharmony_ci CHECK(forwarded.map(cage_base).IsMap(cage_base)); 12241cb0ef41Sopenharmony_ci } 12251cb0ef41Sopenharmony_ci } 12261cb0ef41Sopenharmony_ci } 12271cb0ef41Sopenharmony_ci } else { 12281cb0ef41Sopenharmony_ci Tagged_t compressed_value = 12291cb0ef41Sopenharmony_ci static_cast<Tagged_t>(*spill_slot.location()); 12301cb0ef41Sopenharmony_ci if (!HAS_SMI_TAG(compressed_value)) { 12311cb0ef41Sopenharmony_ci // We don't need to update smi values. 12321cb0ef41Sopenharmony_ci *spill_slot.location() = 12331cb0ef41Sopenharmony_ci DecompressTaggedPointer(cage_base, compressed_value); 12341cb0ef41Sopenharmony_ci } 12351cb0ef41Sopenharmony_ci } 12361cb0ef41Sopenharmony_ci#endif 12371cb0ef41Sopenharmony_ci v->VisitRootPointer(Root::kStackRoots, nullptr, spill_slot); 12381cb0ef41Sopenharmony_ci } 12391cb0ef41Sopenharmony_ci slot_offset += kBitsPerByte; 12401cb0ef41Sopenharmony_ci } 12411cb0ef41Sopenharmony_ci 12421cb0ef41Sopenharmony_ci // Visit tagged parameters that have been passed to the function of this 12431cb0ef41Sopenharmony_ci // frame. Conceptionally these parameters belong to the parent frame. However, 12441cb0ef41Sopenharmony_ci // the exact count is only known by this frame (in the presence of tail calls, 12451cb0ef41Sopenharmony_ci // this information cannot be derived from the call site). 12461cb0ef41Sopenharmony_ci if (num_tagged_parameter_slots > 0) { 12471cb0ef41Sopenharmony_ci FullObjectSlot tagged_parameter_base(&Memory<Address>(caller_sp())); 12481cb0ef41Sopenharmony_ci tagged_parameter_base += first_tagged_parameter_slot; 12491cb0ef41Sopenharmony_ci FullObjectSlot tagged_parameter_limit = 12501cb0ef41Sopenharmony_ci tagged_parameter_base + num_tagged_parameter_slots; 12511cb0ef41Sopenharmony_ci 12521cb0ef41Sopenharmony_ci v->VisitRootPointers(Root::kStackRoots, nullptr, tagged_parameter_base, 12531cb0ef41Sopenharmony_ci tagged_parameter_limit); 12541cb0ef41Sopenharmony_ci } 12551cb0ef41Sopenharmony_ci 12561cb0ef41Sopenharmony_ci // For the off-heap code cases, we can skip this. 12571cb0ef41Sopenharmony_ci if (!code.is_null()) { 12581cb0ef41Sopenharmony_ci // Visit the return address in the callee and incoming arguments. 12591cb0ef41Sopenharmony_ci IteratePc(v, pc_address(), constant_pool_address(), code); 12601cb0ef41Sopenharmony_ci } 12611cb0ef41Sopenharmony_ci 12621cb0ef41Sopenharmony_ci // If this frame has JavaScript ABI, visit the context (in stub and JS 12631cb0ef41Sopenharmony_ci // frames) and the function (in JS frames). If it has WebAssembly ABI, visit 12641cb0ef41Sopenharmony_ci // the instance object. 12651cb0ef41Sopenharmony_ci if (!typed_frame) { 12661cb0ef41Sopenharmony_ci // JavaScript ABI frames also contain arguments count value which is stored 12671cb0ef41Sopenharmony_ci // untagged, we don't need to visit it. 12681cb0ef41Sopenharmony_ci frame_header_base += 1; 12691cb0ef41Sopenharmony_ci } 12701cb0ef41Sopenharmony_ci v->VisitRootPointers(Root::kStackRoots, nullptr, frame_header_base, 12711cb0ef41Sopenharmony_ci frame_header_limit); 12721cb0ef41Sopenharmony_ci} 12731cb0ef41Sopenharmony_ci 12741cb0ef41Sopenharmony_ciCode StubFrame::unchecked_code() const { 12751cb0ef41Sopenharmony_ci return isolate()->FindCodeObject(pc()); 12761cb0ef41Sopenharmony_ci} 12771cb0ef41Sopenharmony_ci 12781cb0ef41Sopenharmony_ciint StubFrame::LookupExceptionHandlerInTable() { 12791cb0ef41Sopenharmony_ci Code code = LookupCode(); 12801cb0ef41Sopenharmony_ci DCHECK(code.is_turbofanned()); 12811cb0ef41Sopenharmony_ci DCHECK_EQ(code.kind(), CodeKind::BUILTIN); 12821cb0ef41Sopenharmony_ci HandlerTable table(code); 12831cb0ef41Sopenharmony_ci int pc_offset = code.GetOffsetFromInstructionStart(isolate(), pc()); 12841cb0ef41Sopenharmony_ci return table.LookupReturn(pc_offset); 12851cb0ef41Sopenharmony_ci} 12861cb0ef41Sopenharmony_ci 12871cb0ef41Sopenharmony_civoid OptimizedFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); } 12881cb0ef41Sopenharmony_ci 12891cb0ef41Sopenharmony_civoid JavaScriptFrame::SetParameterValue(int index, Object value) const { 12901cb0ef41Sopenharmony_ci Memory<Address>(GetParameterSlot(index)) = value.ptr(); 12911cb0ef41Sopenharmony_ci} 12921cb0ef41Sopenharmony_ci 12931cb0ef41Sopenharmony_cibool JavaScriptFrame::IsConstructor() const { 12941cb0ef41Sopenharmony_ci return IsConstructFrame(caller_fp()); 12951cb0ef41Sopenharmony_ci} 12961cb0ef41Sopenharmony_ci 12971cb0ef41Sopenharmony_cibool JavaScriptFrame::HasInlinedFrames() const { 12981cb0ef41Sopenharmony_ci std::vector<SharedFunctionInfo> functions; 12991cb0ef41Sopenharmony_ci GetFunctions(&functions); 13001cb0ef41Sopenharmony_ci return functions.size() > 1; 13011cb0ef41Sopenharmony_ci} 13021cb0ef41Sopenharmony_ci 13031cb0ef41Sopenharmony_ciCode CommonFrameWithJSLinkage::unchecked_code() const { 13041cb0ef41Sopenharmony_ci return FromCodeT(function().code()); 13051cb0ef41Sopenharmony_ci} 13061cb0ef41Sopenharmony_ci 13071cb0ef41Sopenharmony_ciint OptimizedFrame::ComputeParametersCount() const { 13081cb0ef41Sopenharmony_ci Code code = LookupCode(); 13091cb0ef41Sopenharmony_ci if (code.kind() == CodeKind::BUILTIN) { 13101cb0ef41Sopenharmony_ci return static_cast<int>( 13111cb0ef41Sopenharmony_ci Memory<intptr_t>(fp() + StandardFrameConstants::kArgCOffset)) - 13121cb0ef41Sopenharmony_ci kJSArgcReceiverSlots; 13131cb0ef41Sopenharmony_ci } else { 13141cb0ef41Sopenharmony_ci return JavaScriptFrame::ComputeParametersCount(); 13151cb0ef41Sopenharmony_ci } 13161cb0ef41Sopenharmony_ci} 13171cb0ef41Sopenharmony_ci 13181cb0ef41Sopenharmony_ciAddress JavaScriptFrame::GetCallerStackPointer() const { 13191cb0ef41Sopenharmony_ci return fp() + StandardFrameConstants::kCallerSPOffset; 13201cb0ef41Sopenharmony_ci} 13211cb0ef41Sopenharmony_ci 13221cb0ef41Sopenharmony_civoid JavaScriptFrame::GetFunctions( 13231cb0ef41Sopenharmony_ci std::vector<SharedFunctionInfo>* functions) const { 13241cb0ef41Sopenharmony_ci DCHECK(functions->empty()); 13251cb0ef41Sopenharmony_ci functions->push_back(function().shared()); 13261cb0ef41Sopenharmony_ci} 13271cb0ef41Sopenharmony_ci 13281cb0ef41Sopenharmony_civoid JavaScriptFrame::GetFunctions( 13291cb0ef41Sopenharmony_ci std::vector<Handle<SharedFunctionInfo>>* functions) const { 13301cb0ef41Sopenharmony_ci DCHECK(functions->empty()); 13311cb0ef41Sopenharmony_ci std::vector<SharedFunctionInfo> raw_functions; 13321cb0ef41Sopenharmony_ci GetFunctions(&raw_functions); 13331cb0ef41Sopenharmony_ci for (const auto& raw_function : raw_functions) { 13341cb0ef41Sopenharmony_ci functions->push_back( 13351cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo>(raw_function, function().GetIsolate())); 13361cb0ef41Sopenharmony_ci } 13371cb0ef41Sopenharmony_ci} 13381cb0ef41Sopenharmony_ci 13391cb0ef41Sopenharmony_cibool CommonFrameWithJSLinkage::IsConstructor() const { 13401cb0ef41Sopenharmony_ci return IsConstructFrame(caller_fp()); 13411cb0ef41Sopenharmony_ci} 13421cb0ef41Sopenharmony_ci 13431cb0ef41Sopenharmony_civoid CommonFrameWithJSLinkage::Summarize( 13441cb0ef41Sopenharmony_ci std::vector<FrameSummary>* functions) const { 13451cb0ef41Sopenharmony_ci DCHECK(functions->empty()); 13461cb0ef41Sopenharmony_ci Code code = LookupCode(); 13471cb0ef41Sopenharmony_ci int offset = code.GetOffsetFromInstructionStart(isolate(), pc()); 13481cb0ef41Sopenharmony_ci Handle<AbstractCode> abstract_code(AbstractCode::cast(code), isolate()); 13491cb0ef41Sopenharmony_ci Handle<FixedArray> params = GetParameters(); 13501cb0ef41Sopenharmony_ci FrameSummary::JavaScriptFrameSummary summary( 13511cb0ef41Sopenharmony_ci isolate(), receiver(), function(), *abstract_code, offset, 13521cb0ef41Sopenharmony_ci IsConstructor(), *params); 13531cb0ef41Sopenharmony_ci functions->push_back(summary); 13541cb0ef41Sopenharmony_ci} 13551cb0ef41Sopenharmony_ci 13561cb0ef41Sopenharmony_ciJSFunction JavaScriptFrame::function() const { 13571cb0ef41Sopenharmony_ci return JSFunction::cast(function_slot_object()); 13581cb0ef41Sopenharmony_ci} 13591cb0ef41Sopenharmony_ci 13601cb0ef41Sopenharmony_ciObject JavaScriptFrame::unchecked_function() const { 13611cb0ef41Sopenharmony_ci // During deoptimization of an optimized function, we may have yet to 13621cb0ef41Sopenharmony_ci // materialize some closures on the stack. The arguments marker object 13631cb0ef41Sopenharmony_ci // marks this case. 13641cb0ef41Sopenharmony_ci DCHECK(function_slot_object().IsJSFunction() || 13651cb0ef41Sopenharmony_ci ReadOnlyRoots(isolate()).arguments_marker() == function_slot_object()); 13661cb0ef41Sopenharmony_ci return function_slot_object(); 13671cb0ef41Sopenharmony_ci} 13681cb0ef41Sopenharmony_ci 13691cb0ef41Sopenharmony_ciObject CommonFrameWithJSLinkage::receiver() const { return GetParameter(-1); } 13701cb0ef41Sopenharmony_ci 13711cb0ef41Sopenharmony_ciObject JavaScriptFrame::context() const { 13721cb0ef41Sopenharmony_ci const int offset = StandardFrameConstants::kContextOffset; 13731cb0ef41Sopenharmony_ci Object maybe_result(Memory<Address>(fp() + offset)); 13741cb0ef41Sopenharmony_ci DCHECK(!maybe_result.IsSmi()); 13751cb0ef41Sopenharmony_ci return maybe_result; 13761cb0ef41Sopenharmony_ci} 13771cb0ef41Sopenharmony_ci 13781cb0ef41Sopenharmony_ciScript JavaScriptFrame::script() const { 13791cb0ef41Sopenharmony_ci return Script::cast(function().shared().script()); 13801cb0ef41Sopenharmony_ci} 13811cb0ef41Sopenharmony_ci 13821cb0ef41Sopenharmony_ciint CommonFrameWithJSLinkage::LookupExceptionHandlerInTable( 13831cb0ef41Sopenharmony_ci int* stack_depth, HandlerTable::CatchPrediction* prediction) { 13841cb0ef41Sopenharmony_ci DCHECK(!LookupCode().has_handler_table()); 13851cb0ef41Sopenharmony_ci DCHECK(!LookupCode().is_optimized_code() || 13861cb0ef41Sopenharmony_ci LookupCode().kind() == CodeKind::BASELINE); 13871cb0ef41Sopenharmony_ci return -1; 13881cb0ef41Sopenharmony_ci} 13891cb0ef41Sopenharmony_ci 13901cb0ef41Sopenharmony_civoid JavaScriptFrame::PrintFunctionAndOffset(JSFunction function, 13911cb0ef41Sopenharmony_ci AbstractCode code, int code_offset, 13921cb0ef41Sopenharmony_ci FILE* file, 13931cb0ef41Sopenharmony_ci bool print_line_number) { 13941cb0ef41Sopenharmony_ci PrintF(file, "%s", CodeKindToMarker(code.kind())); 13951cb0ef41Sopenharmony_ci function.PrintName(file); 13961cb0ef41Sopenharmony_ci PrintF(file, "+%d", code_offset); 13971cb0ef41Sopenharmony_ci if (print_line_number) { 13981cb0ef41Sopenharmony_ci SharedFunctionInfo shared = function.shared(); 13991cb0ef41Sopenharmony_ci int source_pos = code.SourcePosition(code_offset); 14001cb0ef41Sopenharmony_ci Object maybe_script = shared.script(); 14011cb0ef41Sopenharmony_ci if (maybe_script.IsScript()) { 14021cb0ef41Sopenharmony_ci Script script = Script::cast(maybe_script); 14031cb0ef41Sopenharmony_ci int line = script.GetLineNumber(source_pos) + 1; 14041cb0ef41Sopenharmony_ci Object script_name_raw = script.name(); 14051cb0ef41Sopenharmony_ci if (script_name_raw.IsString()) { 14061cb0ef41Sopenharmony_ci String script_name = String::cast(script.name()); 14071cb0ef41Sopenharmony_ci std::unique_ptr<char[]> c_script_name = 14081cb0ef41Sopenharmony_ci script_name.ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL); 14091cb0ef41Sopenharmony_ci PrintF(file, " at %s:%d", c_script_name.get(), line); 14101cb0ef41Sopenharmony_ci } else { 14111cb0ef41Sopenharmony_ci PrintF(file, " at <unknown>:%d", line); 14121cb0ef41Sopenharmony_ci } 14131cb0ef41Sopenharmony_ci } else { 14141cb0ef41Sopenharmony_ci PrintF(file, " at <unknown>:<unknown>"); 14151cb0ef41Sopenharmony_ci } 14161cb0ef41Sopenharmony_ci } 14171cb0ef41Sopenharmony_ci} 14181cb0ef41Sopenharmony_ci 14191cb0ef41Sopenharmony_civoid JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args, 14201cb0ef41Sopenharmony_ci bool print_line_number) { 14211cb0ef41Sopenharmony_ci // constructor calls 14221cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 14231cb0ef41Sopenharmony_ci JavaScriptFrameIterator it(isolate); 14241cb0ef41Sopenharmony_ci while (!it.done()) { 14251cb0ef41Sopenharmony_ci if (it.frame()->is_java_script()) { 14261cb0ef41Sopenharmony_ci JavaScriptFrame* frame = it.frame(); 14271cb0ef41Sopenharmony_ci if (frame->IsConstructor()) PrintF(file, "new "); 14281cb0ef41Sopenharmony_ci JSFunction function = frame->function(); 14291cb0ef41Sopenharmony_ci int code_offset = 0; 14301cb0ef41Sopenharmony_ci AbstractCode abstract_code = function.abstract_code(isolate); 14311cb0ef41Sopenharmony_ci if (frame->is_interpreted()) { 14321cb0ef41Sopenharmony_ci InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame); 14331cb0ef41Sopenharmony_ci code_offset = iframe->GetBytecodeOffset(); 14341cb0ef41Sopenharmony_ci } else if (frame->is_baseline()) { 14351cb0ef41Sopenharmony_ci // TODO(pthier): AbstractCode should fully support Baseline code. 14361cb0ef41Sopenharmony_ci BaselineFrame* baseline_frame = BaselineFrame::cast(frame); 14371cb0ef41Sopenharmony_ci code_offset = baseline_frame->GetBytecodeOffset(); 14381cb0ef41Sopenharmony_ci abstract_code = AbstractCode::cast(baseline_frame->GetBytecodeArray()); 14391cb0ef41Sopenharmony_ci } else { 14401cb0ef41Sopenharmony_ci Code code = frame->unchecked_code(); 14411cb0ef41Sopenharmony_ci code_offset = code.GetOffsetFromInstructionStart(isolate, frame->pc()); 14421cb0ef41Sopenharmony_ci } 14431cb0ef41Sopenharmony_ci PrintFunctionAndOffset(function, abstract_code, code_offset, file, 14441cb0ef41Sopenharmony_ci print_line_number); 14451cb0ef41Sopenharmony_ci if (print_args) { 14461cb0ef41Sopenharmony_ci // function arguments 14471cb0ef41Sopenharmony_ci // (we are intentionally only printing the actually 14481cb0ef41Sopenharmony_ci // supplied parameters, not all parameters required) 14491cb0ef41Sopenharmony_ci PrintF(file, "(this="); 14501cb0ef41Sopenharmony_ci frame->receiver().ShortPrint(file); 14511cb0ef41Sopenharmony_ci const int length = frame->ComputeParametersCount(); 14521cb0ef41Sopenharmony_ci for (int i = 0; i < length; i++) { 14531cb0ef41Sopenharmony_ci PrintF(file, ", "); 14541cb0ef41Sopenharmony_ci frame->GetParameter(i).ShortPrint(file); 14551cb0ef41Sopenharmony_ci } 14561cb0ef41Sopenharmony_ci PrintF(file, ")"); 14571cb0ef41Sopenharmony_ci } 14581cb0ef41Sopenharmony_ci break; 14591cb0ef41Sopenharmony_ci } 14601cb0ef41Sopenharmony_ci it.Advance(); 14611cb0ef41Sopenharmony_ci } 14621cb0ef41Sopenharmony_ci} 14631cb0ef41Sopenharmony_ci 14641cb0ef41Sopenharmony_civoid JavaScriptFrame::CollectFunctionAndOffsetForICStats(JSFunction function, 14651cb0ef41Sopenharmony_ci AbstractCode code, 14661cb0ef41Sopenharmony_ci int code_offset) { 14671cb0ef41Sopenharmony_ci auto ic_stats = ICStats::instance(); 14681cb0ef41Sopenharmony_ci ICInfo& ic_info = ic_stats->Current(); 14691cb0ef41Sopenharmony_ci SharedFunctionInfo shared = function.shared(); 14701cb0ef41Sopenharmony_ci 14711cb0ef41Sopenharmony_ci ic_info.function_name = ic_stats->GetOrCacheFunctionName(function); 14721cb0ef41Sopenharmony_ci ic_info.script_offset = code_offset; 14731cb0ef41Sopenharmony_ci 14741cb0ef41Sopenharmony_ci int source_pos = code.SourcePosition(code_offset); 14751cb0ef41Sopenharmony_ci Object maybe_script = shared.script(); 14761cb0ef41Sopenharmony_ci if (maybe_script.IsScript()) { 14771cb0ef41Sopenharmony_ci Script script = Script::cast(maybe_script); 14781cb0ef41Sopenharmony_ci ic_info.line_num = script.GetLineNumber(source_pos) + 1; 14791cb0ef41Sopenharmony_ci ic_info.column_num = script.GetColumnNumber(source_pos); 14801cb0ef41Sopenharmony_ci ic_info.script_name = ic_stats->GetOrCacheScriptName(script); 14811cb0ef41Sopenharmony_ci } 14821cb0ef41Sopenharmony_ci} 14831cb0ef41Sopenharmony_ci 14841cb0ef41Sopenharmony_ciObject CommonFrameWithJSLinkage::GetParameter(int index) const { 14851cb0ef41Sopenharmony_ci return Object(Memory<Address>(GetParameterSlot(index))); 14861cb0ef41Sopenharmony_ci} 14871cb0ef41Sopenharmony_ci 14881cb0ef41Sopenharmony_ciint CommonFrameWithJSLinkage::ComputeParametersCount() const { 14891cb0ef41Sopenharmony_ci DCHECK(can_access_heap_objects() && 14901cb0ef41Sopenharmony_ci isolate()->heap()->gc_state() == Heap::NOT_IN_GC); 14911cb0ef41Sopenharmony_ci return function().shared().internal_formal_parameter_count_without_receiver(); 14921cb0ef41Sopenharmony_ci} 14931cb0ef41Sopenharmony_ci 14941cb0ef41Sopenharmony_ciint JavaScriptFrame::GetActualArgumentCount() const { 14951cb0ef41Sopenharmony_ci return static_cast<int>( 14961cb0ef41Sopenharmony_ci Memory<intptr_t>(fp() + StandardFrameConstants::kArgCOffset)) - 14971cb0ef41Sopenharmony_ci kJSArgcReceiverSlots; 14981cb0ef41Sopenharmony_ci} 14991cb0ef41Sopenharmony_ci 15001cb0ef41Sopenharmony_ciHandle<FixedArray> CommonFrameWithJSLinkage::GetParameters() const { 15011cb0ef41Sopenharmony_ci if (V8_LIKELY(!FLAG_detailed_error_stack_trace)) { 15021cb0ef41Sopenharmony_ci return isolate()->factory()->empty_fixed_array(); 15031cb0ef41Sopenharmony_ci } 15041cb0ef41Sopenharmony_ci int param_count = ComputeParametersCount(); 15051cb0ef41Sopenharmony_ci Handle<FixedArray> parameters = 15061cb0ef41Sopenharmony_ci isolate()->factory()->NewFixedArray(param_count); 15071cb0ef41Sopenharmony_ci for (int i = 0; i < param_count; i++) { 15081cb0ef41Sopenharmony_ci parameters->set(i, GetParameter(i)); 15091cb0ef41Sopenharmony_ci } 15101cb0ef41Sopenharmony_ci 15111cb0ef41Sopenharmony_ci return parameters; 15121cb0ef41Sopenharmony_ci} 15131cb0ef41Sopenharmony_ci 15141cb0ef41Sopenharmony_ciJSFunction JavaScriptBuiltinContinuationFrame::function() const { 15151cb0ef41Sopenharmony_ci const int offset = BuiltinContinuationFrameConstants::kFunctionOffset; 15161cb0ef41Sopenharmony_ci return JSFunction::cast(Object(base::Memory<Address>(fp() + offset))); 15171cb0ef41Sopenharmony_ci} 15181cb0ef41Sopenharmony_ci 15191cb0ef41Sopenharmony_ciint JavaScriptBuiltinContinuationFrame::ComputeParametersCount() const { 15201cb0ef41Sopenharmony_ci // Assert that the first allocatable register is also the argument count 15211cb0ef41Sopenharmony_ci // register. 15221cb0ef41Sopenharmony_ci DCHECK_EQ(RegisterConfiguration::Default()->GetAllocatableGeneralCode(0), 15231cb0ef41Sopenharmony_ci kJavaScriptCallArgCountRegister.code()); 15241cb0ef41Sopenharmony_ci Object argc_object( 15251cb0ef41Sopenharmony_ci Memory<Address>(fp() + BuiltinContinuationFrameConstants::kArgCOffset)); 15261cb0ef41Sopenharmony_ci return Smi::ToInt(argc_object) - kJSArgcReceiverSlots; 15271cb0ef41Sopenharmony_ci} 15281cb0ef41Sopenharmony_ci 15291cb0ef41Sopenharmony_ciintptr_t JavaScriptBuiltinContinuationFrame::GetSPToFPDelta() const { 15301cb0ef41Sopenharmony_ci Address height_slot = 15311cb0ef41Sopenharmony_ci fp() + BuiltinContinuationFrameConstants::kFrameSPtoFPDeltaAtDeoptimize; 15321cb0ef41Sopenharmony_ci intptr_t height = Smi::ToInt(Smi(Memory<Address>(height_slot))); 15331cb0ef41Sopenharmony_ci return height; 15341cb0ef41Sopenharmony_ci} 15351cb0ef41Sopenharmony_ci 15361cb0ef41Sopenharmony_ciObject JavaScriptBuiltinContinuationFrame::context() const { 15371cb0ef41Sopenharmony_ci return Object(Memory<Address>( 15381cb0ef41Sopenharmony_ci fp() + BuiltinContinuationFrameConstants::kBuiltinContextOffset)); 15391cb0ef41Sopenharmony_ci} 15401cb0ef41Sopenharmony_ci 15411cb0ef41Sopenharmony_civoid JavaScriptBuiltinContinuationWithCatchFrame::SetException( 15421cb0ef41Sopenharmony_ci Object exception) { 15431cb0ef41Sopenharmony_ci int argc = ComputeParametersCount(); 15441cb0ef41Sopenharmony_ci Address exception_argument_slot = 15451cb0ef41Sopenharmony_ci fp() + BuiltinContinuationFrameConstants::kFixedFrameSizeAboveFp + 15461cb0ef41Sopenharmony_ci (argc - 1) * kSystemPointerSize; 15471cb0ef41Sopenharmony_ci 15481cb0ef41Sopenharmony_ci // Only allow setting exception if previous value was the hole. 15491cb0ef41Sopenharmony_ci CHECK_EQ(ReadOnlyRoots(isolate()).the_hole_value(), 15501cb0ef41Sopenharmony_ci Object(Memory<Address>(exception_argument_slot))); 15511cb0ef41Sopenharmony_ci Memory<Address>(exception_argument_slot) = exception.ptr(); 15521cb0ef41Sopenharmony_ci} 15531cb0ef41Sopenharmony_ci 15541cb0ef41Sopenharmony_ciFrameSummary::JavaScriptFrameSummary::JavaScriptFrameSummary( 15551cb0ef41Sopenharmony_ci Isolate* isolate, Object receiver, JSFunction function, 15561cb0ef41Sopenharmony_ci AbstractCode abstract_code, int code_offset, bool is_constructor, 15571cb0ef41Sopenharmony_ci FixedArray parameters) 15581cb0ef41Sopenharmony_ci : FrameSummaryBase(isolate, FrameSummary::JAVA_SCRIPT), 15591cb0ef41Sopenharmony_ci receiver_(receiver, isolate), 15601cb0ef41Sopenharmony_ci function_(function, isolate), 15611cb0ef41Sopenharmony_ci abstract_code_(abstract_code, isolate), 15621cb0ef41Sopenharmony_ci code_offset_(code_offset), 15631cb0ef41Sopenharmony_ci is_constructor_(is_constructor), 15641cb0ef41Sopenharmony_ci parameters_(parameters, isolate) { 15651cb0ef41Sopenharmony_ci DCHECK(abstract_code.IsBytecodeArray() || 15661cb0ef41Sopenharmony_ci !CodeKindIsOptimizedJSFunction(Code::cast(abstract_code).kind())); 15671cb0ef41Sopenharmony_ci} 15681cb0ef41Sopenharmony_ci 15691cb0ef41Sopenharmony_civoid FrameSummary::EnsureSourcePositionsAvailable() { 15701cb0ef41Sopenharmony_ci if (IsJavaScript()) { 15711cb0ef41Sopenharmony_ci java_script_summary_.EnsureSourcePositionsAvailable(); 15721cb0ef41Sopenharmony_ci } 15731cb0ef41Sopenharmony_ci} 15741cb0ef41Sopenharmony_ci 15751cb0ef41Sopenharmony_cibool FrameSummary::AreSourcePositionsAvailable() const { 15761cb0ef41Sopenharmony_ci if (IsJavaScript()) { 15771cb0ef41Sopenharmony_ci return java_script_summary_.AreSourcePositionsAvailable(); 15781cb0ef41Sopenharmony_ci } 15791cb0ef41Sopenharmony_ci return true; 15801cb0ef41Sopenharmony_ci} 15811cb0ef41Sopenharmony_ci 15821cb0ef41Sopenharmony_civoid FrameSummary::JavaScriptFrameSummary::EnsureSourcePositionsAvailable() { 15831cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared(function()->shared(), isolate()); 15841cb0ef41Sopenharmony_ci SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate(), shared); 15851cb0ef41Sopenharmony_ci} 15861cb0ef41Sopenharmony_ci 15871cb0ef41Sopenharmony_cibool FrameSummary::JavaScriptFrameSummary::AreSourcePositionsAvailable() const { 15881cb0ef41Sopenharmony_ci return !FLAG_enable_lazy_source_positions || function() 15891cb0ef41Sopenharmony_ci ->shared() 15901cb0ef41Sopenharmony_ci .GetBytecodeArray(isolate()) 15911cb0ef41Sopenharmony_ci .HasSourcePositionTable(); 15921cb0ef41Sopenharmony_ci} 15931cb0ef41Sopenharmony_ci 15941cb0ef41Sopenharmony_cibool FrameSummary::JavaScriptFrameSummary::is_subject_to_debugging() const { 15951cb0ef41Sopenharmony_ci return function()->shared().IsSubjectToDebugging(); 15961cb0ef41Sopenharmony_ci} 15971cb0ef41Sopenharmony_ci 15981cb0ef41Sopenharmony_ciint FrameSummary::JavaScriptFrameSummary::SourcePosition() const { 15991cb0ef41Sopenharmony_ci return abstract_code()->SourcePosition(code_offset()); 16001cb0ef41Sopenharmony_ci} 16011cb0ef41Sopenharmony_ci 16021cb0ef41Sopenharmony_ciint FrameSummary::JavaScriptFrameSummary::SourceStatementPosition() const { 16031cb0ef41Sopenharmony_ci return abstract_code()->SourceStatementPosition(code_offset()); 16041cb0ef41Sopenharmony_ci} 16051cb0ef41Sopenharmony_ci 16061cb0ef41Sopenharmony_ciHandle<Object> FrameSummary::JavaScriptFrameSummary::script() const { 16071cb0ef41Sopenharmony_ci return handle(function_->shared().script(), isolate()); 16081cb0ef41Sopenharmony_ci} 16091cb0ef41Sopenharmony_ci 16101cb0ef41Sopenharmony_ciHandle<Context> FrameSummary::JavaScriptFrameSummary::native_context() const { 16111cb0ef41Sopenharmony_ci return handle(function_->native_context(), isolate()); 16121cb0ef41Sopenharmony_ci} 16131cb0ef41Sopenharmony_ci 16141cb0ef41Sopenharmony_ciHandle<StackFrameInfo> 16151cb0ef41Sopenharmony_ciFrameSummary::JavaScriptFrameSummary::CreateStackFrameInfo() const { 16161cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared(function_->shared(), isolate()); 16171cb0ef41Sopenharmony_ci Handle<Script> script(Script::cast(shared->script()), isolate()); 16181cb0ef41Sopenharmony_ci Handle<String> function_name = JSFunction::GetDebugName(function_); 16191cb0ef41Sopenharmony_ci if (function_name->length() == 0 && 16201cb0ef41Sopenharmony_ci script->compilation_type() == Script::COMPILATION_TYPE_EVAL) { 16211cb0ef41Sopenharmony_ci function_name = isolate()->factory()->eval_string(); 16221cb0ef41Sopenharmony_ci } 16231cb0ef41Sopenharmony_ci int bytecode_offset = code_offset(); 16241cb0ef41Sopenharmony_ci if (bytecode_offset == kFunctionEntryBytecodeOffset) { 16251cb0ef41Sopenharmony_ci // For the special function entry bytecode offset (-1), which signals 16261cb0ef41Sopenharmony_ci // that the stack trace was captured while the function entry was 16271cb0ef41Sopenharmony_ci // executing (i.e. during the interrupt check), we cannot store this 16281cb0ef41Sopenharmony_ci // sentinel in the bit field, so we just eagerly lookup the source 16291cb0ef41Sopenharmony_ci // position within the script. 16301cb0ef41Sopenharmony_ci SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate(), shared); 16311cb0ef41Sopenharmony_ci int source_position = abstract_code()->SourcePosition(bytecode_offset); 16321cb0ef41Sopenharmony_ci return isolate()->factory()->NewStackFrameInfo( 16331cb0ef41Sopenharmony_ci script, source_position, function_name, is_constructor()); 16341cb0ef41Sopenharmony_ci } 16351cb0ef41Sopenharmony_ci return isolate()->factory()->NewStackFrameInfo( 16361cb0ef41Sopenharmony_ci shared, bytecode_offset, function_name, is_constructor()); 16371cb0ef41Sopenharmony_ci} 16381cb0ef41Sopenharmony_ci 16391cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 16401cb0ef41Sopenharmony_ciFrameSummary::WasmFrameSummary::WasmFrameSummary( 16411cb0ef41Sopenharmony_ci Isolate* isolate, Handle<WasmInstanceObject> instance, wasm::WasmCode* code, 16421cb0ef41Sopenharmony_ci int code_offset, bool at_to_number_conversion) 16431cb0ef41Sopenharmony_ci : FrameSummaryBase(isolate, WASM), 16441cb0ef41Sopenharmony_ci wasm_instance_(instance), 16451cb0ef41Sopenharmony_ci at_to_number_conversion_(at_to_number_conversion), 16461cb0ef41Sopenharmony_ci code_(code), 16471cb0ef41Sopenharmony_ci code_offset_(code_offset) {} 16481cb0ef41Sopenharmony_ci 16491cb0ef41Sopenharmony_ciHandle<Object> FrameSummary::WasmFrameSummary::receiver() const { 16501cb0ef41Sopenharmony_ci return wasm_instance_->GetIsolate()->global_proxy(); 16511cb0ef41Sopenharmony_ci} 16521cb0ef41Sopenharmony_ci 16531cb0ef41Sopenharmony_ciuint32_t FrameSummary::WasmFrameSummary::function_index() const { 16541cb0ef41Sopenharmony_ci return code()->index(); 16551cb0ef41Sopenharmony_ci} 16561cb0ef41Sopenharmony_ci 16571cb0ef41Sopenharmony_ciint FrameSummary::WasmFrameSummary::byte_offset() const { 16581cb0ef41Sopenharmony_ci return code_->GetSourcePositionBefore(code_offset()); 16591cb0ef41Sopenharmony_ci} 16601cb0ef41Sopenharmony_ci 16611cb0ef41Sopenharmony_ciint FrameSummary::WasmFrameSummary::SourcePosition() const { 16621cb0ef41Sopenharmony_ci const wasm::WasmModule* module = wasm_instance()->module_object().module(); 16631cb0ef41Sopenharmony_ci return GetSourcePosition(module, function_index(), byte_offset(), 16641cb0ef41Sopenharmony_ci at_to_number_conversion()); 16651cb0ef41Sopenharmony_ci} 16661cb0ef41Sopenharmony_ci 16671cb0ef41Sopenharmony_ciHandle<Script> FrameSummary::WasmFrameSummary::script() const { 16681cb0ef41Sopenharmony_ci return handle(wasm_instance()->module_object().script(), 16691cb0ef41Sopenharmony_ci wasm_instance()->GetIsolate()); 16701cb0ef41Sopenharmony_ci} 16711cb0ef41Sopenharmony_ci 16721cb0ef41Sopenharmony_ciHandle<Context> FrameSummary::WasmFrameSummary::native_context() const { 16731cb0ef41Sopenharmony_ci return handle(wasm_instance()->native_context(), isolate()); 16741cb0ef41Sopenharmony_ci} 16751cb0ef41Sopenharmony_ci 16761cb0ef41Sopenharmony_ciHandle<StackFrameInfo> FrameSummary::WasmFrameSummary::CreateStackFrameInfo() 16771cb0ef41Sopenharmony_ci const { 16781cb0ef41Sopenharmony_ci Handle<String> function_name = 16791cb0ef41Sopenharmony_ci GetWasmFunctionDebugName(isolate(), wasm_instance(), function_index()); 16801cb0ef41Sopenharmony_ci return isolate()->factory()->NewStackFrameInfo(script(), SourcePosition(), 16811cb0ef41Sopenharmony_ci function_name, false); 16821cb0ef41Sopenharmony_ci} 16831cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 16841cb0ef41Sopenharmony_ci 16851cb0ef41Sopenharmony_ciFrameSummary::~FrameSummary() { 16861cb0ef41Sopenharmony_ci#define FRAME_SUMMARY_DESTR(kind, type, field, desc) \ 16871cb0ef41Sopenharmony_ci case kind: \ 16881cb0ef41Sopenharmony_ci field.~type(); \ 16891cb0ef41Sopenharmony_ci break; 16901cb0ef41Sopenharmony_ci switch (base_.kind()) { 16911cb0ef41Sopenharmony_ci FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_DESTR) 16921cb0ef41Sopenharmony_ci default: 16931cb0ef41Sopenharmony_ci UNREACHABLE(); 16941cb0ef41Sopenharmony_ci } 16951cb0ef41Sopenharmony_ci#undef FRAME_SUMMARY_DESTR 16961cb0ef41Sopenharmony_ci} 16971cb0ef41Sopenharmony_ci 16981cb0ef41Sopenharmony_ciFrameSummary FrameSummary::GetTop(const CommonFrame* frame) { 16991cb0ef41Sopenharmony_ci std::vector<FrameSummary> frames; 17001cb0ef41Sopenharmony_ci frame->Summarize(&frames); 17011cb0ef41Sopenharmony_ci DCHECK_LT(0, frames.size()); 17021cb0ef41Sopenharmony_ci return frames.back(); 17031cb0ef41Sopenharmony_ci} 17041cb0ef41Sopenharmony_ci 17051cb0ef41Sopenharmony_ciFrameSummary FrameSummary::GetBottom(const CommonFrame* frame) { 17061cb0ef41Sopenharmony_ci return Get(frame, 0); 17071cb0ef41Sopenharmony_ci} 17081cb0ef41Sopenharmony_ci 17091cb0ef41Sopenharmony_ciFrameSummary FrameSummary::GetSingle(const CommonFrame* frame) { 17101cb0ef41Sopenharmony_ci std::vector<FrameSummary> frames; 17111cb0ef41Sopenharmony_ci frame->Summarize(&frames); 17121cb0ef41Sopenharmony_ci DCHECK_EQ(1, frames.size()); 17131cb0ef41Sopenharmony_ci return frames.front(); 17141cb0ef41Sopenharmony_ci} 17151cb0ef41Sopenharmony_ci 17161cb0ef41Sopenharmony_ciFrameSummary FrameSummary::Get(const CommonFrame* frame, int index) { 17171cb0ef41Sopenharmony_ci DCHECK_LE(0, index); 17181cb0ef41Sopenharmony_ci std::vector<FrameSummary> frames; 17191cb0ef41Sopenharmony_ci frame->Summarize(&frames); 17201cb0ef41Sopenharmony_ci DCHECK_GT(frames.size(), index); 17211cb0ef41Sopenharmony_ci return frames[index]; 17221cb0ef41Sopenharmony_ci} 17231cb0ef41Sopenharmony_ci 17241cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 17251cb0ef41Sopenharmony_ci#define FRAME_SUMMARY_DISPATCH(ret, name) \ 17261cb0ef41Sopenharmony_ci ret FrameSummary::name() const { \ 17271cb0ef41Sopenharmony_ci switch (base_.kind()) { \ 17281cb0ef41Sopenharmony_ci case JAVA_SCRIPT: \ 17291cb0ef41Sopenharmony_ci return java_script_summary_.name(); \ 17301cb0ef41Sopenharmony_ci case WASM: \ 17311cb0ef41Sopenharmony_ci return wasm_summary_.name(); \ 17321cb0ef41Sopenharmony_ci default: \ 17331cb0ef41Sopenharmony_ci UNREACHABLE(); \ 17341cb0ef41Sopenharmony_ci } \ 17351cb0ef41Sopenharmony_ci } 17361cb0ef41Sopenharmony_ci#else 17371cb0ef41Sopenharmony_ci#define FRAME_SUMMARY_DISPATCH(ret, name) \ 17381cb0ef41Sopenharmony_ci ret FrameSummary::name() const { \ 17391cb0ef41Sopenharmony_ci DCHECK_EQ(JAVA_SCRIPT, base_.kind()); \ 17401cb0ef41Sopenharmony_ci return java_script_summary_.name(); \ 17411cb0ef41Sopenharmony_ci } 17421cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 17431cb0ef41Sopenharmony_ci 17441cb0ef41Sopenharmony_ciFRAME_SUMMARY_DISPATCH(Handle<Object>, receiver) 17451cb0ef41Sopenharmony_ciFRAME_SUMMARY_DISPATCH(int, code_offset) 17461cb0ef41Sopenharmony_ciFRAME_SUMMARY_DISPATCH(bool, is_constructor) 17471cb0ef41Sopenharmony_ciFRAME_SUMMARY_DISPATCH(bool, is_subject_to_debugging) 17481cb0ef41Sopenharmony_ciFRAME_SUMMARY_DISPATCH(Handle<Object>, script) 17491cb0ef41Sopenharmony_ciFRAME_SUMMARY_DISPATCH(int, SourcePosition) 17501cb0ef41Sopenharmony_ciFRAME_SUMMARY_DISPATCH(int, SourceStatementPosition) 17511cb0ef41Sopenharmony_ciFRAME_SUMMARY_DISPATCH(Handle<Context>, native_context) 17521cb0ef41Sopenharmony_ciFRAME_SUMMARY_DISPATCH(Handle<StackFrameInfo>, CreateStackFrameInfo) 17531cb0ef41Sopenharmony_ci 17541cb0ef41Sopenharmony_ci#undef FRAME_SUMMARY_DISPATCH 17551cb0ef41Sopenharmony_ci 17561cb0ef41Sopenharmony_civoid OptimizedFrame::Summarize(std::vector<FrameSummary>* frames) const { 17571cb0ef41Sopenharmony_ci DCHECK(frames->empty()); 17581cb0ef41Sopenharmony_ci DCHECK(is_optimized()); 17591cb0ef41Sopenharmony_ci 17601cb0ef41Sopenharmony_ci // Delegate to JS frame in absence of turbofan deoptimization. 17611cb0ef41Sopenharmony_ci // TODO(turbofan): Revisit once we support deoptimization across the board. 17621cb0ef41Sopenharmony_ci Code code = LookupCode(); 17631cb0ef41Sopenharmony_ci if (code.kind() == CodeKind::BUILTIN) { 17641cb0ef41Sopenharmony_ci return JavaScriptFrame::Summarize(frames); 17651cb0ef41Sopenharmony_ci } 17661cb0ef41Sopenharmony_ci 17671cb0ef41Sopenharmony_ci int deopt_index = SafepointEntry::kNoDeoptIndex; 17681cb0ef41Sopenharmony_ci DeoptimizationData const data = GetDeoptimizationData(&deopt_index); 17691cb0ef41Sopenharmony_ci if (deopt_index == SafepointEntry::kNoDeoptIndex) { 17701cb0ef41Sopenharmony_ci CHECK(data.is_null()); 17711cb0ef41Sopenharmony_ci FATAL("Missing deoptimization information for OptimizedFrame::Summarize."); 17721cb0ef41Sopenharmony_ci } 17731cb0ef41Sopenharmony_ci 17741cb0ef41Sopenharmony_ci // Prepare iteration over translation. Note that the below iteration might 17751cb0ef41Sopenharmony_ci // materialize objects without storing them back to the Isolate, this will 17761cb0ef41Sopenharmony_ci // lead to objects being re-materialized again for each summary. 17771cb0ef41Sopenharmony_ci TranslatedState translated(this); 17781cb0ef41Sopenharmony_ci translated.Prepare(fp()); 17791cb0ef41Sopenharmony_ci 17801cb0ef41Sopenharmony_ci // We create the summary in reverse order because the frames 17811cb0ef41Sopenharmony_ci // in the deoptimization translation are ordered bottom-to-top. 17821cb0ef41Sopenharmony_ci bool is_constructor = IsConstructor(); 17831cb0ef41Sopenharmony_ci for (auto it = translated.begin(); it != translated.end(); it++) { 17841cb0ef41Sopenharmony_ci if (it->kind() == TranslatedFrame::kUnoptimizedFunction || 17851cb0ef41Sopenharmony_ci it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation || 17861cb0ef41Sopenharmony_ci it->kind() == 17871cb0ef41Sopenharmony_ci TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) { 17881cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared_info = it->shared_info(); 17891cb0ef41Sopenharmony_ci 17901cb0ef41Sopenharmony_ci // The translation commands are ordered and the function is always 17911cb0ef41Sopenharmony_ci // at the first position, and the receiver is next. 17921cb0ef41Sopenharmony_ci TranslatedFrame::iterator translated_values = it->begin(); 17931cb0ef41Sopenharmony_ci 17941cb0ef41Sopenharmony_ci // Get or materialize the correct function in the optimized frame. 17951cb0ef41Sopenharmony_ci Handle<JSFunction> function = 17961cb0ef41Sopenharmony_ci Handle<JSFunction>::cast(translated_values->GetValue()); 17971cb0ef41Sopenharmony_ci translated_values++; 17981cb0ef41Sopenharmony_ci 17991cb0ef41Sopenharmony_ci // Get or materialize the correct receiver in the optimized frame. 18001cb0ef41Sopenharmony_ci Handle<Object> receiver = translated_values->GetValue(); 18011cb0ef41Sopenharmony_ci translated_values++; 18021cb0ef41Sopenharmony_ci 18031cb0ef41Sopenharmony_ci // Determine the underlying code object and the position within it from 18041cb0ef41Sopenharmony_ci // the translation corresponding to the frame type in question. 18051cb0ef41Sopenharmony_ci Handle<AbstractCode> abstract_code; 18061cb0ef41Sopenharmony_ci unsigned code_offset; 18071cb0ef41Sopenharmony_ci if (it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation || 18081cb0ef41Sopenharmony_ci it->kind() == 18091cb0ef41Sopenharmony_ci TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) { 18101cb0ef41Sopenharmony_ci code_offset = 0; 18111cb0ef41Sopenharmony_ci abstract_code = ToAbstractCode( 18121cb0ef41Sopenharmony_ci isolate()->builtins()->code_handle( 18131cb0ef41Sopenharmony_ci Builtins::GetBuiltinFromBytecodeOffset(it->bytecode_offset())), 18141cb0ef41Sopenharmony_ci isolate()); 18151cb0ef41Sopenharmony_ci } else { 18161cb0ef41Sopenharmony_ci DCHECK_EQ(it->kind(), TranslatedFrame::kUnoptimizedFunction); 18171cb0ef41Sopenharmony_ci code_offset = it->bytecode_offset().ToInt(); 18181cb0ef41Sopenharmony_ci abstract_code = 18191cb0ef41Sopenharmony_ci handle(shared_info->abstract_code(isolate()), isolate()); 18201cb0ef41Sopenharmony_ci } 18211cb0ef41Sopenharmony_ci 18221cb0ef41Sopenharmony_ci // Append full summary of the encountered JS frame. 18231cb0ef41Sopenharmony_ci Handle<FixedArray> params = GetParameters(); 18241cb0ef41Sopenharmony_ci FrameSummary::JavaScriptFrameSummary summary( 18251cb0ef41Sopenharmony_ci isolate(), *receiver, *function, *abstract_code, code_offset, 18261cb0ef41Sopenharmony_ci is_constructor, *params); 18271cb0ef41Sopenharmony_ci frames->push_back(summary); 18281cb0ef41Sopenharmony_ci is_constructor = false; 18291cb0ef41Sopenharmony_ci } else if (it->kind() == TranslatedFrame::kConstructStub) { 18301cb0ef41Sopenharmony_ci // The next encountered JS frame will be marked as a constructor call. 18311cb0ef41Sopenharmony_ci DCHECK(!is_constructor); 18321cb0ef41Sopenharmony_ci is_constructor = true; 18331cb0ef41Sopenharmony_ci } 18341cb0ef41Sopenharmony_ci } 18351cb0ef41Sopenharmony_ci} 18361cb0ef41Sopenharmony_ci 18371cb0ef41Sopenharmony_ciint OptimizedFrame::LookupExceptionHandlerInTable( 18381cb0ef41Sopenharmony_ci int* data, HandlerTable::CatchPrediction* prediction) { 18391cb0ef41Sopenharmony_ci // We cannot perform exception prediction on optimized code. Instead, we need 18401cb0ef41Sopenharmony_ci // to use FrameSummary to find the corresponding code offset in unoptimized 18411cb0ef41Sopenharmony_ci // code to perform prediction there. 18421cb0ef41Sopenharmony_ci DCHECK_NULL(prediction); 18431cb0ef41Sopenharmony_ci Code code = LookupCode(); 18441cb0ef41Sopenharmony_ci HandlerTable table(code); 18451cb0ef41Sopenharmony_ci int pc_offset = code.GetOffsetFromInstructionStart(isolate(), pc()); 18461cb0ef41Sopenharmony_ci DCHECK_NULL(data); // Data is not used and will not return a value. 18471cb0ef41Sopenharmony_ci 18481cb0ef41Sopenharmony_ci // When the return pc has been replaced by a trampoline there won't be 18491cb0ef41Sopenharmony_ci // a handler for this trampoline. Thus we need to use the return pc that 18501cb0ef41Sopenharmony_ci // _used to be_ on the stack to get the right ExceptionHandler. 18511cb0ef41Sopenharmony_ci if (CodeKindCanDeoptimize(code.kind()) && code.marked_for_deoptimization()) { 18521cb0ef41Sopenharmony_ci SafepointTable safepoints(isolate(), pc(), code); 18531cb0ef41Sopenharmony_ci pc_offset = safepoints.find_return_pc(pc_offset); 18541cb0ef41Sopenharmony_ci } 18551cb0ef41Sopenharmony_ci return table.LookupReturn(pc_offset); 18561cb0ef41Sopenharmony_ci} 18571cb0ef41Sopenharmony_ci 18581cb0ef41Sopenharmony_ciDeoptimizationData OptimizedFrame::GetDeoptimizationData( 18591cb0ef41Sopenharmony_ci int* deopt_index) const { 18601cb0ef41Sopenharmony_ci DCHECK(is_optimized()); 18611cb0ef41Sopenharmony_ci 18621cb0ef41Sopenharmony_ci JSFunction opt_function = function(); 18631cb0ef41Sopenharmony_ci Code code = FromCodeT(opt_function.code()); 18641cb0ef41Sopenharmony_ci 18651cb0ef41Sopenharmony_ci // The code object may have been replaced by lazy deoptimization. Fall 18661cb0ef41Sopenharmony_ci // back to a slow search in this case to find the original optimized 18671cb0ef41Sopenharmony_ci // code object. 18681cb0ef41Sopenharmony_ci if (!code.contains(isolate(), pc())) { 18691cb0ef41Sopenharmony_ci code = isolate()->heap()->GcSafeFindCodeForInnerPointer(pc()); 18701cb0ef41Sopenharmony_ci } 18711cb0ef41Sopenharmony_ci DCHECK(!code.is_null()); 18721cb0ef41Sopenharmony_ci DCHECK(CodeKindCanDeoptimize(code.kind())); 18731cb0ef41Sopenharmony_ci 18741cb0ef41Sopenharmony_ci SafepointEntry safepoint_entry = code.GetSafepointEntry(isolate(), pc()); 18751cb0ef41Sopenharmony_ci if (safepoint_entry.has_deoptimization_index()) { 18761cb0ef41Sopenharmony_ci *deopt_index = safepoint_entry.deoptimization_index(); 18771cb0ef41Sopenharmony_ci return DeoptimizationData::cast(code.deoptimization_data()); 18781cb0ef41Sopenharmony_ci } 18791cb0ef41Sopenharmony_ci *deopt_index = SafepointEntry::kNoDeoptIndex; 18801cb0ef41Sopenharmony_ci return DeoptimizationData(); 18811cb0ef41Sopenharmony_ci} 18821cb0ef41Sopenharmony_ci 18831cb0ef41Sopenharmony_civoid OptimizedFrame::GetFunctions( 18841cb0ef41Sopenharmony_ci std::vector<SharedFunctionInfo>* functions) const { 18851cb0ef41Sopenharmony_ci DCHECK(functions->empty()); 18861cb0ef41Sopenharmony_ci DCHECK(is_optimized()); 18871cb0ef41Sopenharmony_ci 18881cb0ef41Sopenharmony_ci // Delegate to JS frame in absence of turbofan deoptimization. 18891cb0ef41Sopenharmony_ci // TODO(turbofan): Revisit once we support deoptimization across the board. 18901cb0ef41Sopenharmony_ci Code code = LookupCode(); 18911cb0ef41Sopenharmony_ci if (code.kind() == CodeKind::BUILTIN) { 18921cb0ef41Sopenharmony_ci return JavaScriptFrame::GetFunctions(functions); 18931cb0ef41Sopenharmony_ci } 18941cb0ef41Sopenharmony_ci 18951cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 18961cb0ef41Sopenharmony_ci int deopt_index = SafepointEntry::kNoDeoptIndex; 18971cb0ef41Sopenharmony_ci DeoptimizationData const data = GetDeoptimizationData(&deopt_index); 18981cb0ef41Sopenharmony_ci DCHECK(!data.is_null()); 18991cb0ef41Sopenharmony_ci DCHECK_NE(SafepointEntry::kNoDeoptIndex, deopt_index); 19001cb0ef41Sopenharmony_ci DeoptimizationLiteralArray const literal_array = data.LiteralArray(); 19011cb0ef41Sopenharmony_ci 19021cb0ef41Sopenharmony_ci TranslationArrayIterator it(data.TranslationByteArray(), 19031cb0ef41Sopenharmony_ci data.TranslationIndex(deopt_index).value()); 19041cb0ef41Sopenharmony_ci TranslationOpcode opcode = TranslationOpcodeFromInt(it.Next()); 19051cb0ef41Sopenharmony_ci DCHECK_EQ(TranslationOpcode::BEGIN, opcode); 19061cb0ef41Sopenharmony_ci it.Next(); // Skip frame count. 19071cb0ef41Sopenharmony_ci int jsframe_count = it.Next(); 19081cb0ef41Sopenharmony_ci it.Next(); // Skip update feedback count. 19091cb0ef41Sopenharmony_ci 19101cb0ef41Sopenharmony_ci // We insert the frames in reverse order because the frames 19111cb0ef41Sopenharmony_ci // in the deoptimization translation are ordered bottom-to-top. 19121cb0ef41Sopenharmony_ci while (jsframe_count != 0) { 19131cb0ef41Sopenharmony_ci opcode = TranslationOpcodeFromInt(it.Next()); 19141cb0ef41Sopenharmony_ci if (opcode == TranslationOpcode::INTERPRETED_FRAME || 19151cb0ef41Sopenharmony_ci opcode == TranslationOpcode::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME || 19161cb0ef41Sopenharmony_ci opcode == TranslationOpcode:: 19171cb0ef41Sopenharmony_ci JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME) { 19181cb0ef41Sopenharmony_ci it.Next(); // Skip bailout id. 19191cb0ef41Sopenharmony_ci jsframe_count--; 19201cb0ef41Sopenharmony_ci 19211cb0ef41Sopenharmony_ci // The second operand of the frame points to the function. 19221cb0ef41Sopenharmony_ci Object shared = literal_array.get(it.Next()); 19231cb0ef41Sopenharmony_ci functions->push_back(SharedFunctionInfo::cast(shared)); 19241cb0ef41Sopenharmony_ci 19251cb0ef41Sopenharmony_ci // Skip over remaining operands to advance to the next opcode. 19261cb0ef41Sopenharmony_ci it.Skip(TranslationOpcodeOperandCount(opcode) - 2); 19271cb0ef41Sopenharmony_ci } else { 19281cb0ef41Sopenharmony_ci // Skip over operands to advance to the next opcode. 19291cb0ef41Sopenharmony_ci it.Skip(TranslationOpcodeOperandCount(opcode)); 19301cb0ef41Sopenharmony_ci } 19311cb0ef41Sopenharmony_ci } 19321cb0ef41Sopenharmony_ci} 19331cb0ef41Sopenharmony_ci 19341cb0ef41Sopenharmony_ciint OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) { 19351cb0ef41Sopenharmony_ci return StandardFrameConstants::kCallerSPOffset - 19361cb0ef41Sopenharmony_ci ((slot_index + 1) * kSystemPointerSize); 19371cb0ef41Sopenharmony_ci} 19381cb0ef41Sopenharmony_ci 19391cb0ef41Sopenharmony_ciObject OptimizedFrame::StackSlotAt(int index) const { 19401cb0ef41Sopenharmony_ci return Object(Memory<Address>(fp() + StackSlotOffsetRelativeToFp(index))); 19411cb0ef41Sopenharmony_ci} 19421cb0ef41Sopenharmony_ci 19431cb0ef41Sopenharmony_ciint UnoptimizedFrame::position() const { 19441cb0ef41Sopenharmony_ci AbstractCode code = AbstractCode::cast(GetBytecodeArray()); 19451cb0ef41Sopenharmony_ci int code_offset = GetBytecodeOffset(); 19461cb0ef41Sopenharmony_ci return code.SourcePosition(code_offset); 19471cb0ef41Sopenharmony_ci} 19481cb0ef41Sopenharmony_ci 19491cb0ef41Sopenharmony_ciint UnoptimizedFrame::LookupExceptionHandlerInTable( 19501cb0ef41Sopenharmony_ci int* context_register, HandlerTable::CatchPrediction* prediction) { 19511cb0ef41Sopenharmony_ci HandlerTable table(GetBytecodeArray()); 19521cb0ef41Sopenharmony_ci return table.LookupRange(GetBytecodeOffset(), context_register, prediction); 19531cb0ef41Sopenharmony_ci} 19541cb0ef41Sopenharmony_ci 19551cb0ef41Sopenharmony_ciBytecodeArray UnoptimizedFrame::GetBytecodeArray() const { 19561cb0ef41Sopenharmony_ci const int index = UnoptimizedFrameConstants::kBytecodeArrayExpressionIndex; 19571cb0ef41Sopenharmony_ci DCHECK_EQ(UnoptimizedFrameConstants::kBytecodeArrayFromFp, 19581cb0ef41Sopenharmony_ci UnoptimizedFrameConstants::kExpressionsOffset - 19591cb0ef41Sopenharmony_ci index * kSystemPointerSize); 19601cb0ef41Sopenharmony_ci return BytecodeArray::cast(GetExpression(index)); 19611cb0ef41Sopenharmony_ci} 19621cb0ef41Sopenharmony_ci 19631cb0ef41Sopenharmony_ciObject UnoptimizedFrame::ReadInterpreterRegister(int register_index) const { 19641cb0ef41Sopenharmony_ci const int index = UnoptimizedFrameConstants::kRegisterFileExpressionIndex; 19651cb0ef41Sopenharmony_ci DCHECK_EQ(UnoptimizedFrameConstants::kRegisterFileFromFp, 19661cb0ef41Sopenharmony_ci UnoptimizedFrameConstants::kExpressionsOffset - 19671cb0ef41Sopenharmony_ci index * kSystemPointerSize); 19681cb0ef41Sopenharmony_ci return GetExpression(index + register_index); 19691cb0ef41Sopenharmony_ci} 19701cb0ef41Sopenharmony_ci 19711cb0ef41Sopenharmony_civoid UnoptimizedFrame::Summarize(std::vector<FrameSummary>* functions) const { 19721cb0ef41Sopenharmony_ci DCHECK(functions->empty()); 19731cb0ef41Sopenharmony_ci Handle<AbstractCode> abstract_code(AbstractCode::cast(GetBytecodeArray()), 19741cb0ef41Sopenharmony_ci isolate()); 19751cb0ef41Sopenharmony_ci Handle<FixedArray> params = GetParameters(); 19761cb0ef41Sopenharmony_ci FrameSummary::JavaScriptFrameSummary summary( 19771cb0ef41Sopenharmony_ci isolate(), receiver(), function(), *abstract_code, GetBytecodeOffset(), 19781cb0ef41Sopenharmony_ci IsConstructor(), *params); 19791cb0ef41Sopenharmony_ci functions->push_back(summary); 19801cb0ef41Sopenharmony_ci} 19811cb0ef41Sopenharmony_ci 19821cb0ef41Sopenharmony_ciint InterpretedFrame::GetBytecodeOffset() const { 19831cb0ef41Sopenharmony_ci const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex; 19841cb0ef41Sopenharmony_ci DCHECK_EQ(InterpreterFrameConstants::kBytecodeOffsetFromFp, 19851cb0ef41Sopenharmony_ci InterpreterFrameConstants::kExpressionsOffset - 19861cb0ef41Sopenharmony_ci index * kSystemPointerSize); 19871cb0ef41Sopenharmony_ci int raw_offset = Smi::ToInt(GetExpression(index)); 19881cb0ef41Sopenharmony_ci return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag; 19891cb0ef41Sopenharmony_ci} 19901cb0ef41Sopenharmony_ci 19911cb0ef41Sopenharmony_ci// static 19921cb0ef41Sopenharmony_ciint InterpretedFrame::GetBytecodeOffset(Address fp) { 19931cb0ef41Sopenharmony_ci const int offset = InterpreterFrameConstants::kExpressionsOffset; 19941cb0ef41Sopenharmony_ci const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex; 19951cb0ef41Sopenharmony_ci DCHECK_EQ(InterpreterFrameConstants::kBytecodeOffsetFromFp, 19961cb0ef41Sopenharmony_ci InterpreterFrameConstants::kExpressionsOffset - 19971cb0ef41Sopenharmony_ci index * kSystemPointerSize); 19981cb0ef41Sopenharmony_ci Address expression_offset = fp + offset - index * kSystemPointerSize; 19991cb0ef41Sopenharmony_ci int raw_offset = Smi::ToInt(Object(Memory<Address>(expression_offset))); 20001cb0ef41Sopenharmony_ci return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag; 20011cb0ef41Sopenharmony_ci} 20021cb0ef41Sopenharmony_ci 20031cb0ef41Sopenharmony_civoid InterpretedFrame::PatchBytecodeOffset(int new_offset) { 20041cb0ef41Sopenharmony_ci const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex; 20051cb0ef41Sopenharmony_ci DCHECK_EQ(InterpreterFrameConstants::kBytecodeOffsetFromFp, 20061cb0ef41Sopenharmony_ci InterpreterFrameConstants::kExpressionsOffset - 20071cb0ef41Sopenharmony_ci index * kSystemPointerSize); 20081cb0ef41Sopenharmony_ci int raw_offset = BytecodeArray::kHeaderSize - kHeapObjectTag + new_offset; 20091cb0ef41Sopenharmony_ci SetExpression(index, Smi::FromInt(raw_offset)); 20101cb0ef41Sopenharmony_ci} 20111cb0ef41Sopenharmony_ci 20121cb0ef41Sopenharmony_civoid InterpretedFrame::PatchBytecodeArray(BytecodeArray bytecode_array) { 20131cb0ef41Sopenharmony_ci const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex; 20141cb0ef41Sopenharmony_ci DCHECK_EQ(InterpreterFrameConstants::kBytecodeArrayFromFp, 20151cb0ef41Sopenharmony_ci InterpreterFrameConstants::kExpressionsOffset - 20161cb0ef41Sopenharmony_ci index * kSystemPointerSize); 20171cb0ef41Sopenharmony_ci SetExpression(index, bytecode_array); 20181cb0ef41Sopenharmony_ci} 20191cb0ef41Sopenharmony_ci 20201cb0ef41Sopenharmony_ciint BaselineFrame::GetBytecodeOffset() const { 20211cb0ef41Sopenharmony_ci return LookupCode().GetBytecodeOffsetForBaselinePC(this->pc(), 20221cb0ef41Sopenharmony_ci GetBytecodeArray()); 20231cb0ef41Sopenharmony_ci} 20241cb0ef41Sopenharmony_ci 20251cb0ef41Sopenharmony_ciintptr_t BaselineFrame::GetPCForBytecodeOffset(int bytecode_offset) const { 20261cb0ef41Sopenharmony_ci return LookupCode().GetBaselineStartPCForBytecodeOffset(bytecode_offset, 20271cb0ef41Sopenharmony_ci GetBytecodeArray()); 20281cb0ef41Sopenharmony_ci} 20291cb0ef41Sopenharmony_ci 20301cb0ef41Sopenharmony_civoid BaselineFrame::PatchContext(Context value) { 20311cb0ef41Sopenharmony_ci base::Memory<Address>(fp() + BaselineFrameConstants::kContextOffset) = 20321cb0ef41Sopenharmony_ci value.ptr(); 20331cb0ef41Sopenharmony_ci} 20341cb0ef41Sopenharmony_ci 20351cb0ef41Sopenharmony_ciJSFunction BuiltinFrame::function() const { 20361cb0ef41Sopenharmony_ci const int offset = BuiltinFrameConstants::kFunctionOffset; 20371cb0ef41Sopenharmony_ci return JSFunction::cast(Object(base::Memory<Address>(fp() + offset))); 20381cb0ef41Sopenharmony_ci} 20391cb0ef41Sopenharmony_ci 20401cb0ef41Sopenharmony_ciint BuiltinFrame::ComputeParametersCount() const { 20411cb0ef41Sopenharmony_ci const int offset = BuiltinFrameConstants::kLengthOffset; 20421cb0ef41Sopenharmony_ci return Smi::ToInt(Object(base::Memory<Address>(fp() + offset))) - 20431cb0ef41Sopenharmony_ci kJSArgcReceiverSlots; 20441cb0ef41Sopenharmony_ci} 20451cb0ef41Sopenharmony_ci 20461cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 20471cb0ef41Sopenharmony_civoid WasmFrame::Print(StringStream* accumulator, PrintMode mode, 20481cb0ef41Sopenharmony_ci int index) const { 20491cb0ef41Sopenharmony_ci PrintIndex(accumulator, mode, index); 20501cb0ef41Sopenharmony_ci if (function_index() == wasm::kAnonymousFuncIndex) { 20511cb0ef41Sopenharmony_ci accumulator->Add("Anonymous wasm wrapper [pc: %p]\n", 20521cb0ef41Sopenharmony_ci reinterpret_cast<void*>(pc())); 20531cb0ef41Sopenharmony_ci return; 20541cb0ef41Sopenharmony_ci } 20551cb0ef41Sopenharmony_ci wasm::WasmCodeRefScope code_ref_scope; 20561cb0ef41Sopenharmony_ci accumulator->Add("Wasm ["); 20571cb0ef41Sopenharmony_ci accumulator->PrintName(script().name()); 20581cb0ef41Sopenharmony_ci Address instruction_start = wasm_code()->instruction_start(); 20591cb0ef41Sopenharmony_ci base::Vector<const uint8_t> raw_func_name = 20601cb0ef41Sopenharmony_ci module_object().GetRawFunctionName(function_index()); 20611cb0ef41Sopenharmony_ci const int kMaxPrintedFunctionName = 64; 20621cb0ef41Sopenharmony_ci char func_name[kMaxPrintedFunctionName + 1]; 20631cb0ef41Sopenharmony_ci int func_name_len = std::min(kMaxPrintedFunctionName, raw_func_name.length()); 20641cb0ef41Sopenharmony_ci memcpy(func_name, raw_func_name.begin(), func_name_len); 20651cb0ef41Sopenharmony_ci func_name[func_name_len] = '\0'; 20661cb0ef41Sopenharmony_ci int pos = position(); 20671cb0ef41Sopenharmony_ci const wasm::WasmModule* module = wasm_instance().module_object().module(); 20681cb0ef41Sopenharmony_ci int func_index = function_index(); 20691cb0ef41Sopenharmony_ci int func_code_offset = module->functions[func_index].code.offset(); 20701cb0ef41Sopenharmony_ci accumulator->Add("], function #%u ('%s'), pc=%p (+0x%x), pos=%d (+%d)\n", 20711cb0ef41Sopenharmony_ci func_index, func_name, reinterpret_cast<void*>(pc()), 20721cb0ef41Sopenharmony_ci static_cast<int>(pc() - instruction_start), pos, 20731cb0ef41Sopenharmony_ci pos - func_code_offset); 20741cb0ef41Sopenharmony_ci if (mode != OVERVIEW) accumulator->Add("\n"); 20751cb0ef41Sopenharmony_ci} 20761cb0ef41Sopenharmony_ci 20771cb0ef41Sopenharmony_ciwasm::WasmCode* WasmFrame::wasm_code() const { 20781cb0ef41Sopenharmony_ci return wasm::GetWasmCodeManager()->LookupCode(pc()); 20791cb0ef41Sopenharmony_ci} 20801cb0ef41Sopenharmony_ci 20811cb0ef41Sopenharmony_ciWasmInstanceObject WasmFrame::wasm_instance() const { 20821cb0ef41Sopenharmony_ci const int offset = WasmFrameConstants::kWasmInstanceOffset; 20831cb0ef41Sopenharmony_ci Object instance(Memory<Address>(fp() + offset)); 20841cb0ef41Sopenharmony_ci return WasmInstanceObject::cast(instance); 20851cb0ef41Sopenharmony_ci} 20861cb0ef41Sopenharmony_ci 20871cb0ef41Sopenharmony_ciwasm::NativeModule* WasmFrame::native_module() const { 20881cb0ef41Sopenharmony_ci return module_object().native_module(); 20891cb0ef41Sopenharmony_ci} 20901cb0ef41Sopenharmony_ci 20911cb0ef41Sopenharmony_ciWasmModuleObject WasmFrame::module_object() const { 20921cb0ef41Sopenharmony_ci return wasm_instance().module_object(); 20931cb0ef41Sopenharmony_ci} 20941cb0ef41Sopenharmony_ci 20951cb0ef41Sopenharmony_ciint WasmFrame::function_index() const { 20961cb0ef41Sopenharmony_ci wasm::WasmCodeRefScope code_ref_scope; 20971cb0ef41Sopenharmony_ci return wasm_code()->index(); 20981cb0ef41Sopenharmony_ci} 20991cb0ef41Sopenharmony_ci 21001cb0ef41Sopenharmony_ciScript WasmFrame::script() const { return module_object().script(); } 21011cb0ef41Sopenharmony_ci 21021cb0ef41Sopenharmony_ciint WasmFrame::position() const { 21031cb0ef41Sopenharmony_ci wasm::WasmCodeRefScope code_ref_scope; 21041cb0ef41Sopenharmony_ci const wasm::WasmModule* module = wasm_instance().module_object().module(); 21051cb0ef41Sopenharmony_ci return GetSourcePosition(module, function_index(), byte_offset(), 21061cb0ef41Sopenharmony_ci at_to_number_conversion()); 21071cb0ef41Sopenharmony_ci} 21081cb0ef41Sopenharmony_ci 21091cb0ef41Sopenharmony_ciint WasmFrame::byte_offset() const { 21101cb0ef41Sopenharmony_ci wasm::WasmCode* code = wasm_code(); 21111cb0ef41Sopenharmony_ci int offset = static_cast<int>(pc() - code->instruction_start()); 21121cb0ef41Sopenharmony_ci return code->GetSourcePositionBefore(offset); 21131cb0ef41Sopenharmony_ci} 21141cb0ef41Sopenharmony_ci 21151cb0ef41Sopenharmony_cibool WasmFrame::is_inspectable() const { 21161cb0ef41Sopenharmony_ci wasm::WasmCodeRefScope code_ref_scope; 21171cb0ef41Sopenharmony_ci return wasm_code()->is_inspectable(); 21181cb0ef41Sopenharmony_ci} 21191cb0ef41Sopenharmony_ci 21201cb0ef41Sopenharmony_ciObject WasmFrame::context() const { return wasm_instance().native_context(); } 21211cb0ef41Sopenharmony_ci 21221cb0ef41Sopenharmony_civoid WasmFrame::Summarize(std::vector<FrameSummary>* functions) const { 21231cb0ef41Sopenharmony_ci DCHECK(functions->empty()); 21241cb0ef41Sopenharmony_ci // The {WasmCode*} escapes this scope via the {FrameSummary}, which is fine, 21251cb0ef41Sopenharmony_ci // since this code object is part of our stack. 21261cb0ef41Sopenharmony_ci wasm::WasmCodeRefScope code_ref_scope; 21271cb0ef41Sopenharmony_ci wasm::WasmCode* code = wasm_code(); 21281cb0ef41Sopenharmony_ci int offset = static_cast<int>(pc() - code->instruction_start()); 21291cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance(wasm_instance(), isolate()); 21301cb0ef41Sopenharmony_ci FrameSummary::WasmFrameSummary summary(isolate(), instance, code, offset, 21311cb0ef41Sopenharmony_ci at_to_number_conversion()); 21321cb0ef41Sopenharmony_ci functions->push_back(summary); 21331cb0ef41Sopenharmony_ci} 21341cb0ef41Sopenharmony_ci 21351cb0ef41Sopenharmony_cibool WasmFrame::at_to_number_conversion() const { 21361cb0ef41Sopenharmony_ci // Check whether our callee is a WASM_TO_JS frame, and this frame is at the 21371cb0ef41Sopenharmony_ci // ToNumber conversion call. 21381cb0ef41Sopenharmony_ci wasm::WasmCode* code = 21391cb0ef41Sopenharmony_ci callee_pc() != kNullAddress 21401cb0ef41Sopenharmony_ci ? wasm::GetWasmCodeManager()->LookupCode(callee_pc()) 21411cb0ef41Sopenharmony_ci : nullptr; 21421cb0ef41Sopenharmony_ci if (!code || code->kind() != wasm::WasmCode::kWasmToJsWrapper) return false; 21431cb0ef41Sopenharmony_ci int offset = static_cast<int>(callee_pc() - code->instruction_start()); 21441cb0ef41Sopenharmony_ci int pos = code->GetSourcePositionBefore(offset); 21451cb0ef41Sopenharmony_ci // The imported call has position 0, ToNumber has position 1. 21461cb0ef41Sopenharmony_ci // If there is no source position available, this is also not a ToNumber call. 21471cb0ef41Sopenharmony_ci DCHECK(pos == wasm::kNoCodePosition || pos == 0 || pos == 1); 21481cb0ef41Sopenharmony_ci return pos == 1; 21491cb0ef41Sopenharmony_ci} 21501cb0ef41Sopenharmony_ci 21511cb0ef41Sopenharmony_ciint WasmFrame::LookupExceptionHandlerInTable() { 21521cb0ef41Sopenharmony_ci wasm::WasmCode* code = wasm::GetWasmCodeManager()->LookupCode(pc()); 21531cb0ef41Sopenharmony_ci if (!code->IsAnonymous() && code->handler_table_size() > 0) { 21541cb0ef41Sopenharmony_ci HandlerTable table(code); 21551cb0ef41Sopenharmony_ci int pc_offset = static_cast<int>(pc() - code->instruction_start()); 21561cb0ef41Sopenharmony_ci return table.LookupReturn(pc_offset); 21571cb0ef41Sopenharmony_ci } 21581cb0ef41Sopenharmony_ci return -1; 21591cb0ef41Sopenharmony_ci} 21601cb0ef41Sopenharmony_ci 21611cb0ef41Sopenharmony_civoid WasmDebugBreakFrame::Iterate(RootVisitor* v) const { 21621cb0ef41Sopenharmony_ci DCHECK(caller_pc()); 21631cb0ef41Sopenharmony_ci wasm::WasmCode* code = wasm::GetWasmCodeManager()->LookupCode(caller_pc()); 21641cb0ef41Sopenharmony_ci DCHECK(code); 21651cb0ef41Sopenharmony_ci SafepointTable table(code); 21661cb0ef41Sopenharmony_ci SafepointEntry safepoint_entry = table.FindEntry(caller_pc()); 21671cb0ef41Sopenharmony_ci uint32_t tagged_register_indexes = safepoint_entry.tagged_register_indexes(); 21681cb0ef41Sopenharmony_ci 21691cb0ef41Sopenharmony_ci while (tagged_register_indexes != 0) { 21701cb0ef41Sopenharmony_ci int reg_code = base::bits::CountTrailingZeros(tagged_register_indexes); 21711cb0ef41Sopenharmony_ci tagged_register_indexes &= ~(1 << reg_code); 21721cb0ef41Sopenharmony_ci FullObjectSlot spill_slot(&Memory<Address>( 21731cb0ef41Sopenharmony_ci fp() + 21741cb0ef41Sopenharmony_ci WasmDebugBreakFrameConstants::GetPushedGpRegisterOffset(reg_code))); 21751cb0ef41Sopenharmony_ci 21761cb0ef41Sopenharmony_ci v->VisitRootPointer(Root::kStackRoots, nullptr, spill_slot); 21771cb0ef41Sopenharmony_ci } 21781cb0ef41Sopenharmony_ci} 21791cb0ef41Sopenharmony_ci 21801cb0ef41Sopenharmony_civoid WasmDebugBreakFrame::Print(StringStream* accumulator, PrintMode mode, 21811cb0ef41Sopenharmony_ci int index) const { 21821cb0ef41Sopenharmony_ci PrintIndex(accumulator, mode, index); 21831cb0ef41Sopenharmony_ci accumulator->Add("WasmDebugBreak"); 21841cb0ef41Sopenharmony_ci if (mode != OVERVIEW) accumulator->Add("\n"); 21851cb0ef41Sopenharmony_ci} 21861cb0ef41Sopenharmony_ci 21871cb0ef41Sopenharmony_civoid JsToWasmFrame::Iterate(RootVisitor* v) const { 21881cb0ef41Sopenharmony_ci Code code = GetContainingCode(isolate(), pc()); 21891cb0ef41Sopenharmony_ci // GenericJSToWasmWrapper stack layout 21901cb0ef41Sopenharmony_ci // ------+-----------------+---------------------- 21911cb0ef41Sopenharmony_ci // | return addr | 21921cb0ef41Sopenharmony_ci // fp |- - - - - - - - -| -------------------| 21931cb0ef41Sopenharmony_ci // | fp | | 21941cb0ef41Sopenharmony_ci // fp-p |- - - - - - - - -| | 21951cb0ef41Sopenharmony_ci // | frame marker | | no GC scan 21961cb0ef41Sopenharmony_ci // fp-2p |- - - - - - - - -| | 21971cb0ef41Sopenharmony_ci // | scan_count | | 21981cb0ef41Sopenharmony_ci // fp-3p |- - - - - - - - -| -------------------| 21991cb0ef41Sopenharmony_ci // | .... | <- spill_slot_limit | 22001cb0ef41Sopenharmony_ci // | spill slots | | GC scan scan_count slots 22011cb0ef41Sopenharmony_ci // | .... | <- spill_slot_base--| 22021cb0ef41Sopenharmony_ci // |- - - - - - - - -| | 22031cb0ef41Sopenharmony_ci if (code.is_null() || !code.is_builtin() || 22041cb0ef41Sopenharmony_ci code.builtin_id() != Builtin::kGenericJSToWasmWrapper) { 22051cb0ef41Sopenharmony_ci // If it's not the GenericJSToWasmWrapper, then it's the TurboFan compiled 22061cb0ef41Sopenharmony_ci // specific wrapper. So we have to call IterateCompiledFrame. 22071cb0ef41Sopenharmony_ci IterateCompiledFrame(v); 22081cb0ef41Sopenharmony_ci return; 22091cb0ef41Sopenharmony_ci } 22101cb0ef41Sopenharmony_ci // The [fp + BuiltinFrameConstants::kGCScanSlotCount] on the stack is a value 22111cb0ef41Sopenharmony_ci // indicating how many values should be scanned from the top. 22121cb0ef41Sopenharmony_ci intptr_t scan_count = *reinterpret_cast<intptr_t*>( 22131cb0ef41Sopenharmony_ci fp() + BuiltinWasmWrapperConstants::kGCScanSlotCountOffset); 22141cb0ef41Sopenharmony_ci 22151cb0ef41Sopenharmony_ci FullObjectSlot spill_slot_base(&Memory<Address>(sp())); 22161cb0ef41Sopenharmony_ci FullObjectSlot spill_slot_limit( 22171cb0ef41Sopenharmony_ci &Memory<Address>(sp() + scan_count * kSystemPointerSize)); 22181cb0ef41Sopenharmony_ci v->VisitRootPointers(Root::kStackRoots, nullptr, spill_slot_base, 22191cb0ef41Sopenharmony_ci spill_slot_limit); 22201cb0ef41Sopenharmony_ci} 22211cb0ef41Sopenharmony_ci 22221cb0ef41Sopenharmony_civoid StackSwitchFrame::Iterate(RootVisitor* v) const { 22231cb0ef41Sopenharmony_ci // See JsToWasmFrame layout. 22241cb0ef41Sopenharmony_ci // We cannot DCHECK that the pc matches the expected builtin code here, 22251cb0ef41Sopenharmony_ci // because the return address is on a different stack. 22261cb0ef41Sopenharmony_ci // The [fp + BuiltinFrameConstants::kGCScanSlotCountOffset] on the stack is a 22271cb0ef41Sopenharmony_ci // value indicating how many values should be scanned from the top. 22281cb0ef41Sopenharmony_ci intptr_t scan_count = *reinterpret_cast<intptr_t*>( 22291cb0ef41Sopenharmony_ci fp() + BuiltinWasmWrapperConstants::kGCScanSlotCountOffset); 22301cb0ef41Sopenharmony_ci 22311cb0ef41Sopenharmony_ci FullObjectSlot spill_slot_base(&Memory<Address>(sp())); 22321cb0ef41Sopenharmony_ci FullObjectSlot spill_slot_limit( 22331cb0ef41Sopenharmony_ci &Memory<Address>(sp() + scan_count * kSystemPointerSize)); 22341cb0ef41Sopenharmony_ci v->VisitRootPointers(Root::kStackRoots, nullptr, spill_slot_base, 22351cb0ef41Sopenharmony_ci spill_slot_limit); 22361cb0ef41Sopenharmony_ci} 22371cb0ef41Sopenharmony_ci 22381cb0ef41Sopenharmony_ci// static 22391cb0ef41Sopenharmony_civoid StackSwitchFrame::GetStateForJumpBuffer(wasm::JumpBuffer* jmpbuf, 22401cb0ef41Sopenharmony_ci State* state) { 22411cb0ef41Sopenharmony_ci DCHECK_NE(jmpbuf->fp, kNullAddress); 22421cb0ef41Sopenharmony_ci DCHECK_EQ(ComputeFrameType(jmpbuf->fp), STACK_SWITCH); 22431cb0ef41Sopenharmony_ci FillState(jmpbuf->fp, jmpbuf->sp, state); 22441cb0ef41Sopenharmony_ci DCHECK_NE(*state->pc_address, kNullAddress); 22451cb0ef41Sopenharmony_ci} 22461cb0ef41Sopenharmony_ci 22471cb0ef41Sopenharmony_ciWasmInstanceObject WasmCompileLazyFrame::wasm_instance() const { 22481cb0ef41Sopenharmony_ci return WasmInstanceObject::cast(*wasm_instance_slot()); 22491cb0ef41Sopenharmony_ci} 22501cb0ef41Sopenharmony_ci 22511cb0ef41Sopenharmony_ciFullObjectSlot WasmCompileLazyFrame::wasm_instance_slot() const { 22521cb0ef41Sopenharmony_ci const int offset = WasmCompileLazyFrameConstants::kWasmInstanceOffset; 22531cb0ef41Sopenharmony_ci return FullObjectSlot(&Memory<Address>(fp() + offset)); 22541cb0ef41Sopenharmony_ci} 22551cb0ef41Sopenharmony_ci 22561cb0ef41Sopenharmony_civoid WasmCompileLazyFrame::Iterate(RootVisitor* v) const { 22571cb0ef41Sopenharmony_ci const int header_size = WasmCompileLazyFrameConstants::kFixedFrameSizeFromFp; 22581cb0ef41Sopenharmony_ci FullObjectSlot base(&Memory<Address>(sp())); 22591cb0ef41Sopenharmony_ci FullObjectSlot limit(&Memory<Address>(fp() - header_size)); 22601cb0ef41Sopenharmony_ci v->VisitRootPointers(Root::kStackRoots, nullptr, base, limit); 22611cb0ef41Sopenharmony_ci v->VisitRootPointer(Root::kStackRoots, nullptr, wasm_instance_slot()); 22621cb0ef41Sopenharmony_ci} 22631cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 22641cb0ef41Sopenharmony_ci 22651cb0ef41Sopenharmony_cinamespace { 22661cb0ef41Sopenharmony_ci 22671cb0ef41Sopenharmony_civoid PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo shared, 22681cb0ef41Sopenharmony_ci Code code) { 22691cb0ef41Sopenharmony_ci if (FLAG_max_stack_trace_source_length != 0 && !code.is_null()) { 22701cb0ef41Sopenharmony_ci std::ostringstream os; 22711cb0ef41Sopenharmony_ci os << "--------- s o u r c e c o d e ---------\n" 22721cb0ef41Sopenharmony_ci << SourceCodeOf(shared, FLAG_max_stack_trace_source_length) 22731cb0ef41Sopenharmony_ci << "\n-----------------------------------------\n"; 22741cb0ef41Sopenharmony_ci accumulator->Add(os.str().c_str()); 22751cb0ef41Sopenharmony_ci } 22761cb0ef41Sopenharmony_ci} 22771cb0ef41Sopenharmony_ci 22781cb0ef41Sopenharmony_ci} // namespace 22791cb0ef41Sopenharmony_ci 22801cb0ef41Sopenharmony_civoid JavaScriptFrame::Print(StringStream* accumulator, PrintMode mode, 22811cb0ef41Sopenharmony_ci int index) const { 22821cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared = handle(function().shared(), isolate()); 22831cb0ef41Sopenharmony_ci SharedFunctionInfo::EnsureSourcePositionsAvailable(isolate(), shared); 22841cb0ef41Sopenharmony_ci 22851cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 22861cb0ef41Sopenharmony_ci Object receiver = this->receiver(); 22871cb0ef41Sopenharmony_ci JSFunction function = this->function(); 22881cb0ef41Sopenharmony_ci 22891cb0ef41Sopenharmony_ci accumulator->PrintSecurityTokenIfChanged(function); 22901cb0ef41Sopenharmony_ci PrintIndex(accumulator, mode, index); 22911cb0ef41Sopenharmony_ci PrintFrameKind(accumulator); 22921cb0ef41Sopenharmony_ci Code code; 22931cb0ef41Sopenharmony_ci if (IsConstructor()) accumulator->Add("new "); 22941cb0ef41Sopenharmony_ci accumulator->PrintFunction(function, receiver, &code); 22951cb0ef41Sopenharmony_ci accumulator->Add(" [%p]", function); 22961cb0ef41Sopenharmony_ci 22971cb0ef41Sopenharmony_ci // Get scope information for nicer output, if possible. If code is nullptr, or 22981cb0ef41Sopenharmony_ci // doesn't contain scope info, scope_info will return 0 for the number of 22991cb0ef41Sopenharmony_ci // parameters, stack local variables, context local variables, stack slots, 23001cb0ef41Sopenharmony_ci // or context slots. 23011cb0ef41Sopenharmony_ci ScopeInfo scope_info = shared->scope_info(); 23021cb0ef41Sopenharmony_ci Object script_obj = shared->script(); 23031cb0ef41Sopenharmony_ci if (script_obj.IsScript()) { 23041cb0ef41Sopenharmony_ci Script script = Script::cast(script_obj); 23051cb0ef41Sopenharmony_ci accumulator->Add(" ["); 23061cb0ef41Sopenharmony_ci accumulator->PrintName(script.name()); 23071cb0ef41Sopenharmony_ci 23081cb0ef41Sopenharmony_ci if (is_interpreted()) { 23091cb0ef41Sopenharmony_ci const InterpretedFrame* iframe = InterpretedFrame::cast(this); 23101cb0ef41Sopenharmony_ci BytecodeArray bytecodes = iframe->GetBytecodeArray(); 23111cb0ef41Sopenharmony_ci int offset = iframe->GetBytecodeOffset(); 23121cb0ef41Sopenharmony_ci int source_pos = AbstractCode::cast(bytecodes).SourcePosition(offset); 23131cb0ef41Sopenharmony_ci int line = script.GetLineNumber(source_pos) + 1; 23141cb0ef41Sopenharmony_ci accumulator->Add(":%d] [bytecode=%p offset=%d]", line, 23151cb0ef41Sopenharmony_ci reinterpret_cast<void*>(bytecodes.ptr()), offset); 23161cb0ef41Sopenharmony_ci } else { 23171cb0ef41Sopenharmony_ci int function_start_pos = shared->StartPosition(); 23181cb0ef41Sopenharmony_ci int line = script.GetLineNumber(function_start_pos) + 1; 23191cb0ef41Sopenharmony_ci accumulator->Add(":~%d] [pc=%p]", line, reinterpret_cast<void*>(pc())); 23201cb0ef41Sopenharmony_ci } 23211cb0ef41Sopenharmony_ci } 23221cb0ef41Sopenharmony_ci 23231cb0ef41Sopenharmony_ci accumulator->Add("(this=%o", receiver); 23241cb0ef41Sopenharmony_ci 23251cb0ef41Sopenharmony_ci // Print the parameters. 23261cb0ef41Sopenharmony_ci int parameters_count = ComputeParametersCount(); 23271cb0ef41Sopenharmony_ci for (int i = 0; i < parameters_count; i++) { 23281cb0ef41Sopenharmony_ci accumulator->Add(","); 23291cb0ef41Sopenharmony_ci accumulator->Add("%o", GetParameter(i)); 23301cb0ef41Sopenharmony_ci } 23311cb0ef41Sopenharmony_ci 23321cb0ef41Sopenharmony_ci accumulator->Add(")"); 23331cb0ef41Sopenharmony_ci if (mode == OVERVIEW) { 23341cb0ef41Sopenharmony_ci accumulator->Add("\n"); 23351cb0ef41Sopenharmony_ci return; 23361cb0ef41Sopenharmony_ci } 23371cb0ef41Sopenharmony_ci if (is_optimized()) { 23381cb0ef41Sopenharmony_ci accumulator->Add(" {\n// optimized frame\n"); 23391cb0ef41Sopenharmony_ci PrintFunctionSource(accumulator, *shared, code); 23401cb0ef41Sopenharmony_ci accumulator->Add("}\n"); 23411cb0ef41Sopenharmony_ci return; 23421cb0ef41Sopenharmony_ci } 23431cb0ef41Sopenharmony_ci accumulator->Add(" {\n"); 23441cb0ef41Sopenharmony_ci 23451cb0ef41Sopenharmony_ci // Compute the number of locals and expression stack elements. 23461cb0ef41Sopenharmony_ci int heap_locals_count = scope_info.ContextLocalCount(); 23471cb0ef41Sopenharmony_ci int expressions_count = ComputeExpressionsCount(); 23481cb0ef41Sopenharmony_ci 23491cb0ef41Sopenharmony_ci // Try to get hold of the context of this frame. 23501cb0ef41Sopenharmony_ci Context context; 23511cb0ef41Sopenharmony_ci if (this->context().IsContext()) { 23521cb0ef41Sopenharmony_ci context = Context::cast(this->context()); 23531cb0ef41Sopenharmony_ci while (context.IsWithContext()) { 23541cb0ef41Sopenharmony_ci context = context.previous(); 23551cb0ef41Sopenharmony_ci DCHECK(!context.is_null()); 23561cb0ef41Sopenharmony_ci } 23571cb0ef41Sopenharmony_ci } 23581cb0ef41Sopenharmony_ci 23591cb0ef41Sopenharmony_ci // Print heap-allocated local variables. 23601cb0ef41Sopenharmony_ci if (heap_locals_count > 0) { 23611cb0ef41Sopenharmony_ci accumulator->Add(" // heap-allocated locals\n"); 23621cb0ef41Sopenharmony_ci } 23631cb0ef41Sopenharmony_ci for (auto it : ScopeInfo::IterateLocalNames(&scope_info, no_gc)) { 23641cb0ef41Sopenharmony_ci accumulator->Add(" var "); 23651cb0ef41Sopenharmony_ci accumulator->PrintName(it->name()); 23661cb0ef41Sopenharmony_ci accumulator->Add(" = "); 23671cb0ef41Sopenharmony_ci if (!context.is_null()) { 23681cb0ef41Sopenharmony_ci int slot_index = Context::MIN_CONTEXT_SLOTS + it->index(); 23691cb0ef41Sopenharmony_ci if (slot_index < context.length()) { 23701cb0ef41Sopenharmony_ci accumulator->Add("%o", context.get(slot_index)); 23711cb0ef41Sopenharmony_ci } else { 23721cb0ef41Sopenharmony_ci accumulator->Add( 23731cb0ef41Sopenharmony_ci "// warning: missing context slot - inconsistent frame?"); 23741cb0ef41Sopenharmony_ci } 23751cb0ef41Sopenharmony_ci } else { 23761cb0ef41Sopenharmony_ci accumulator->Add("// warning: no context found - inconsistent frame?"); 23771cb0ef41Sopenharmony_ci } 23781cb0ef41Sopenharmony_ci accumulator->Add("\n"); 23791cb0ef41Sopenharmony_ci } 23801cb0ef41Sopenharmony_ci 23811cb0ef41Sopenharmony_ci // Print the expression stack. 23821cb0ef41Sopenharmony_ci if (0 < expressions_count) { 23831cb0ef41Sopenharmony_ci accumulator->Add(" // expression stack (top to bottom)\n"); 23841cb0ef41Sopenharmony_ci } 23851cb0ef41Sopenharmony_ci for (int i = expressions_count - 1; i >= 0; i--) { 23861cb0ef41Sopenharmony_ci accumulator->Add(" [%02d] : %o\n", i, GetExpression(i)); 23871cb0ef41Sopenharmony_ci } 23881cb0ef41Sopenharmony_ci 23891cb0ef41Sopenharmony_ci PrintFunctionSource(accumulator, *shared, code); 23901cb0ef41Sopenharmony_ci 23911cb0ef41Sopenharmony_ci accumulator->Add("}\n\n"); 23921cb0ef41Sopenharmony_ci} 23931cb0ef41Sopenharmony_ci 23941cb0ef41Sopenharmony_civoid EntryFrame::Iterate(RootVisitor* v) const { 23951cb0ef41Sopenharmony_ci IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 23961cb0ef41Sopenharmony_ci} 23971cb0ef41Sopenharmony_ci 23981cb0ef41Sopenharmony_civoid CommonFrame::IterateExpressions(RootVisitor* v) const { 23991cb0ef41Sopenharmony_ci const int last_object_offset = StandardFrameConstants::kLastObjectOffset; 24001cb0ef41Sopenharmony_ci intptr_t marker = 24011cb0ef41Sopenharmony_ci Memory<intptr_t>(fp() + CommonFrameConstants::kContextOrFrameTypeOffset); 24021cb0ef41Sopenharmony_ci FullObjectSlot base(&Memory<Address>(sp())); 24031cb0ef41Sopenharmony_ci FullObjectSlot limit(&Memory<Address>(fp() + last_object_offset) + 1); 24041cb0ef41Sopenharmony_ci if (StackFrame::IsTypeMarker(marker)) { 24051cb0ef41Sopenharmony_ci v->VisitRootPointers(Root::kStackRoots, nullptr, base, limit); 24061cb0ef41Sopenharmony_ci } else { 24071cb0ef41Sopenharmony_ci // The frame contains the actual argument count (intptr) that should not be 24081cb0ef41Sopenharmony_ci // visited. 24091cb0ef41Sopenharmony_ci FullObjectSlot argc( 24101cb0ef41Sopenharmony_ci &Memory<Address>(fp() + StandardFrameConstants::kArgCOffset)); 24111cb0ef41Sopenharmony_ci v->VisitRootPointers(Root::kStackRoots, nullptr, base, argc); 24121cb0ef41Sopenharmony_ci v->VisitRootPointers(Root::kStackRoots, nullptr, argc + 1, limit); 24131cb0ef41Sopenharmony_ci } 24141cb0ef41Sopenharmony_ci} 24151cb0ef41Sopenharmony_ci 24161cb0ef41Sopenharmony_civoid JavaScriptFrame::Iterate(RootVisitor* v) const { 24171cb0ef41Sopenharmony_ci IterateExpressions(v); 24181cb0ef41Sopenharmony_ci IteratePc(v, pc_address(), constant_pool_address(), LookupCode()); 24191cb0ef41Sopenharmony_ci} 24201cb0ef41Sopenharmony_ci 24211cb0ef41Sopenharmony_civoid InternalFrame::Iterate(RootVisitor* v) const { 24221cb0ef41Sopenharmony_ci Code code = LookupCode(); 24231cb0ef41Sopenharmony_ci IteratePc(v, pc_address(), constant_pool_address(), code); 24241cb0ef41Sopenharmony_ci // Internal frames typically do not receive any arguments, hence their stack 24251cb0ef41Sopenharmony_ci // only contains tagged pointers. 24261cb0ef41Sopenharmony_ci // We are misusing the has_tagged_outgoing_params flag here to tell us whether 24271cb0ef41Sopenharmony_ci // the full stack frame contains only tagged pointers or only raw values. 24281cb0ef41Sopenharmony_ci // This is used for the WasmCompileLazy builtin, where we actually pass 24291cb0ef41Sopenharmony_ci // untagged arguments and also store untagged values on the stack. 24301cb0ef41Sopenharmony_ci if (code.has_tagged_outgoing_params()) IterateExpressions(v); 24311cb0ef41Sopenharmony_ci} 24321cb0ef41Sopenharmony_ci 24331cb0ef41Sopenharmony_ci// ------------------------------------------------------------------------- 24341cb0ef41Sopenharmony_ci 24351cb0ef41Sopenharmony_cinamespace { 24361cb0ef41Sopenharmony_ci 24371cb0ef41Sopenharmony_ci// Predictably converts PC to uint32 by calculating offset of the PC in 24381cb0ef41Sopenharmony_ci// from the embedded builtins start or from respective MemoryChunk. 24391cb0ef41Sopenharmony_ciuint32_t PcAddressForHashing(Isolate* isolate, Address address) { 24401cb0ef41Sopenharmony_ci uint32_t hashable_address; 24411cb0ef41Sopenharmony_ci if (OffHeapInstructionStream::TryGetAddressForHashing(isolate, address, 24421cb0ef41Sopenharmony_ci &hashable_address)) { 24431cb0ef41Sopenharmony_ci return hashable_address; 24441cb0ef41Sopenharmony_ci } 24451cb0ef41Sopenharmony_ci return ObjectAddressForHashing(address); 24461cb0ef41Sopenharmony_ci} 24471cb0ef41Sopenharmony_ci 24481cb0ef41Sopenharmony_ci} // namespace 24491cb0ef41Sopenharmony_ci 24501cb0ef41Sopenharmony_ciInnerPointerToCodeCache::InnerPointerToCodeCacheEntry* 24511cb0ef41Sopenharmony_ciInnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) { 24521cb0ef41Sopenharmony_ci isolate_->counters()->pc_to_code()->Increment(); 24531cb0ef41Sopenharmony_ci DCHECK(base::bits::IsPowerOfTwo(kInnerPointerToCodeCacheSize)); 24541cb0ef41Sopenharmony_ci uint32_t hash = 24551cb0ef41Sopenharmony_ci ComputeUnseededHash(PcAddressForHashing(isolate_, inner_pointer)); 24561cb0ef41Sopenharmony_ci uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1); 24571cb0ef41Sopenharmony_ci InnerPointerToCodeCacheEntry* entry = cache(index); 24581cb0ef41Sopenharmony_ci if (entry->inner_pointer == inner_pointer) { 24591cb0ef41Sopenharmony_ci isolate_->counters()->pc_to_code_cached()->Increment(); 24601cb0ef41Sopenharmony_ci DCHECK(entry->code == 24611cb0ef41Sopenharmony_ci isolate_->heap()->GcSafeFindCodeForInnerPointer(inner_pointer)); 24621cb0ef41Sopenharmony_ci } else { 24631cb0ef41Sopenharmony_ci // Because this code may be interrupted by a profiling signal that 24641cb0ef41Sopenharmony_ci // also queries the cache, we cannot update inner_pointer before the code 24651cb0ef41Sopenharmony_ci // has been set. Otherwise, we risk trying to use a cache entry before 24661cb0ef41Sopenharmony_ci // the code has been computed. 24671cb0ef41Sopenharmony_ci entry->code = 24681cb0ef41Sopenharmony_ci isolate_->heap()->GcSafeFindCodeForInnerPointer(inner_pointer); 24691cb0ef41Sopenharmony_ci entry->safepoint_entry.Reset(); 24701cb0ef41Sopenharmony_ci entry->inner_pointer = inner_pointer; 24711cb0ef41Sopenharmony_ci } 24721cb0ef41Sopenharmony_ci return entry; 24731cb0ef41Sopenharmony_ci} 24741cb0ef41Sopenharmony_ci 24751cb0ef41Sopenharmony_ci// Frame layout helper class implementation. 24761cb0ef41Sopenharmony_ci// ------------------------------------------------------------------------- 24771cb0ef41Sopenharmony_ci 24781cb0ef41Sopenharmony_cinamespace { 24791cb0ef41Sopenharmony_ci 24801cb0ef41Sopenharmony_ci// Some architectures need to push padding together with the TOS register 24811cb0ef41Sopenharmony_ci// in order to maintain stack alignment. 24821cb0ef41Sopenharmony_ciconstexpr int TopOfStackRegisterPaddingSlots() { 24831cb0ef41Sopenharmony_ci return ArgumentPaddingSlots(1); 24841cb0ef41Sopenharmony_ci} 24851cb0ef41Sopenharmony_ci 24861cb0ef41Sopenharmony_cibool BuiltinContinuationModeIsWithCatch(BuiltinContinuationMode mode) { 24871cb0ef41Sopenharmony_ci switch (mode) { 24881cb0ef41Sopenharmony_ci case BuiltinContinuationMode::STUB: 24891cb0ef41Sopenharmony_ci case BuiltinContinuationMode::JAVASCRIPT: 24901cb0ef41Sopenharmony_ci return false; 24911cb0ef41Sopenharmony_ci case BuiltinContinuationMode::JAVASCRIPT_WITH_CATCH: 24921cb0ef41Sopenharmony_ci case BuiltinContinuationMode::JAVASCRIPT_HANDLE_EXCEPTION: 24931cb0ef41Sopenharmony_ci return true; 24941cb0ef41Sopenharmony_ci } 24951cb0ef41Sopenharmony_ci UNREACHABLE(); 24961cb0ef41Sopenharmony_ci} 24971cb0ef41Sopenharmony_ci 24981cb0ef41Sopenharmony_ci} // namespace 24991cb0ef41Sopenharmony_ci 25001cb0ef41Sopenharmony_ciUnoptimizedFrameInfo::UnoptimizedFrameInfo(int parameters_count_with_receiver, 25011cb0ef41Sopenharmony_ci int translation_height, 25021cb0ef41Sopenharmony_ci bool is_topmost, bool pad_arguments, 25031cb0ef41Sopenharmony_ci FrameInfoKind frame_info_kind) { 25041cb0ef41Sopenharmony_ci const int locals_count = translation_height; 25051cb0ef41Sopenharmony_ci 25061cb0ef41Sopenharmony_ci register_stack_slot_count_ = 25071cb0ef41Sopenharmony_ci UnoptimizedFrameConstants::RegisterStackSlotCount(locals_count); 25081cb0ef41Sopenharmony_ci 25091cb0ef41Sopenharmony_ci static constexpr int kTheAccumulator = 1; 25101cb0ef41Sopenharmony_ci static constexpr int kTopOfStackPadding = TopOfStackRegisterPaddingSlots(); 25111cb0ef41Sopenharmony_ci int maybe_additional_slots = 25121cb0ef41Sopenharmony_ci (is_topmost || frame_info_kind == FrameInfoKind::kConservative) 25131cb0ef41Sopenharmony_ci ? (kTheAccumulator + kTopOfStackPadding) 25141cb0ef41Sopenharmony_ci : 0; 25151cb0ef41Sopenharmony_ci frame_size_in_bytes_without_fixed_ = 25161cb0ef41Sopenharmony_ci (register_stack_slot_count_ + maybe_additional_slots) * 25171cb0ef41Sopenharmony_ci kSystemPointerSize; 25181cb0ef41Sopenharmony_ci 25191cb0ef41Sopenharmony_ci // The 'fixed' part of the frame consists of the incoming parameters and 25201cb0ef41Sopenharmony_ci // the part described by InterpreterFrameConstants. This will include 25211cb0ef41Sopenharmony_ci // argument padding, when needed. 25221cb0ef41Sopenharmony_ci const int parameter_padding_slots = 25231cb0ef41Sopenharmony_ci pad_arguments ? ArgumentPaddingSlots(parameters_count_with_receiver) : 0; 25241cb0ef41Sopenharmony_ci const int fixed_frame_size = 25251cb0ef41Sopenharmony_ci InterpreterFrameConstants::kFixedFrameSize + 25261cb0ef41Sopenharmony_ci (parameters_count_with_receiver + parameter_padding_slots) * 25271cb0ef41Sopenharmony_ci kSystemPointerSize; 25281cb0ef41Sopenharmony_ci frame_size_in_bytes_ = frame_size_in_bytes_without_fixed_ + fixed_frame_size; 25291cb0ef41Sopenharmony_ci} 25301cb0ef41Sopenharmony_ci 25311cb0ef41Sopenharmony_ci// static 25321cb0ef41Sopenharmony_ciuint32_t UnoptimizedFrameInfo::GetStackSizeForAdditionalArguments( 25331cb0ef41Sopenharmony_ci int parameters_count) { 25341cb0ef41Sopenharmony_ci return (parameters_count + ArgumentPaddingSlots(parameters_count)) * 25351cb0ef41Sopenharmony_ci kSystemPointerSize; 25361cb0ef41Sopenharmony_ci} 25371cb0ef41Sopenharmony_ci 25381cb0ef41Sopenharmony_ciConstructStubFrameInfo::ConstructStubFrameInfo(int translation_height, 25391cb0ef41Sopenharmony_ci bool is_topmost, 25401cb0ef41Sopenharmony_ci FrameInfoKind frame_info_kind) { 25411cb0ef41Sopenharmony_ci // Note: This is according to the Translation's notion of 'parameters' which 25421cb0ef41Sopenharmony_ci // differs to that of the SharedFunctionInfo, e.g. by including the receiver. 25431cb0ef41Sopenharmony_ci const int parameters_count = translation_height; 25441cb0ef41Sopenharmony_ci 25451cb0ef41Sopenharmony_ci // If the construct frame appears to be topmost we should ensure that the 25461cb0ef41Sopenharmony_ci // value of result register is preserved during continuation execution. 25471cb0ef41Sopenharmony_ci // We do this here by "pushing" the result of the constructor function to 25481cb0ef41Sopenharmony_ci // the top of the reconstructed stack and popping it in 25491cb0ef41Sopenharmony_ci // {Builtin::kNotifyDeoptimized}. 25501cb0ef41Sopenharmony_ci 25511cb0ef41Sopenharmony_ci static constexpr int kTopOfStackPadding = TopOfStackRegisterPaddingSlots(); 25521cb0ef41Sopenharmony_ci static constexpr int kTheResult = 1; 25531cb0ef41Sopenharmony_ci const int argument_padding = ArgumentPaddingSlots(parameters_count); 25541cb0ef41Sopenharmony_ci 25551cb0ef41Sopenharmony_ci const int adjusted_height = 25561cb0ef41Sopenharmony_ci (is_topmost || frame_info_kind == FrameInfoKind::kConservative) 25571cb0ef41Sopenharmony_ci ? parameters_count + argument_padding + kTheResult + 25581cb0ef41Sopenharmony_ci kTopOfStackPadding 25591cb0ef41Sopenharmony_ci : parameters_count + argument_padding; 25601cb0ef41Sopenharmony_ci frame_size_in_bytes_without_fixed_ = adjusted_height * kSystemPointerSize; 25611cb0ef41Sopenharmony_ci frame_size_in_bytes_ = frame_size_in_bytes_without_fixed_ + 25621cb0ef41Sopenharmony_ci ConstructFrameConstants::kFixedFrameSize; 25631cb0ef41Sopenharmony_ci} 25641cb0ef41Sopenharmony_ci 25651cb0ef41Sopenharmony_ciBuiltinContinuationFrameInfo::BuiltinContinuationFrameInfo( 25661cb0ef41Sopenharmony_ci int translation_height, 25671cb0ef41Sopenharmony_ci const CallInterfaceDescriptor& continuation_descriptor, 25681cb0ef41Sopenharmony_ci const RegisterConfiguration* register_config, bool is_topmost, 25691cb0ef41Sopenharmony_ci DeoptimizeKind deopt_kind, BuiltinContinuationMode continuation_mode, 25701cb0ef41Sopenharmony_ci FrameInfoKind frame_info_kind) { 25711cb0ef41Sopenharmony_ci const bool is_conservative = frame_info_kind == FrameInfoKind::kConservative; 25721cb0ef41Sopenharmony_ci 25731cb0ef41Sopenharmony_ci // Note: This is according to the Translation's notion of 'parameters' which 25741cb0ef41Sopenharmony_ci // differs to that of the SharedFunctionInfo, e.g. by including the receiver. 25751cb0ef41Sopenharmony_ci const int parameters_count = translation_height; 25761cb0ef41Sopenharmony_ci frame_has_result_stack_slot_ = 25771cb0ef41Sopenharmony_ci !is_topmost || deopt_kind == DeoptimizeKind::kLazy; 25781cb0ef41Sopenharmony_ci const int result_slot_count = 25791cb0ef41Sopenharmony_ci (frame_has_result_stack_slot_ || is_conservative) ? 1 : 0; 25801cb0ef41Sopenharmony_ci 25811cb0ef41Sopenharmony_ci const int exception_slot_count = 25821cb0ef41Sopenharmony_ci (BuiltinContinuationModeIsWithCatch(continuation_mode) || is_conservative) 25831cb0ef41Sopenharmony_ci ? 1 25841cb0ef41Sopenharmony_ci : 0; 25851cb0ef41Sopenharmony_ci 25861cb0ef41Sopenharmony_ci const int allocatable_register_count = 25871cb0ef41Sopenharmony_ci register_config->num_allocatable_general_registers(); 25881cb0ef41Sopenharmony_ci const int padding_slot_count = 25891cb0ef41Sopenharmony_ci BuiltinContinuationFrameConstants::PaddingSlotCount( 25901cb0ef41Sopenharmony_ci allocatable_register_count); 25911cb0ef41Sopenharmony_ci 25921cb0ef41Sopenharmony_ci const int register_parameter_count = 25931cb0ef41Sopenharmony_ci continuation_descriptor.GetRegisterParameterCount(); 25941cb0ef41Sopenharmony_ci translated_stack_parameter_count_ = 25951cb0ef41Sopenharmony_ci parameters_count - register_parameter_count; 25961cb0ef41Sopenharmony_ci stack_parameter_count_ = translated_stack_parameter_count_ + 25971cb0ef41Sopenharmony_ci result_slot_count + exception_slot_count; 25981cb0ef41Sopenharmony_ci const int stack_param_pad_count = 25991cb0ef41Sopenharmony_ci ArgumentPaddingSlots(stack_parameter_count_); 26001cb0ef41Sopenharmony_ci 26011cb0ef41Sopenharmony_ci // If the builtins frame appears to be topmost we should ensure that the 26021cb0ef41Sopenharmony_ci // value of result register is preserved during continuation execution. 26031cb0ef41Sopenharmony_ci // We do this here by "pushing" the result of callback function to the 26041cb0ef41Sopenharmony_ci // top of the reconstructed stack and popping it in 26051cb0ef41Sopenharmony_ci // {Builtin::kNotifyDeoptimized}. 26061cb0ef41Sopenharmony_ci static constexpr int kTopOfStackPadding = TopOfStackRegisterPaddingSlots(); 26071cb0ef41Sopenharmony_ci static constexpr int kTheResult = 1; 26081cb0ef41Sopenharmony_ci const int push_result_count = 26091cb0ef41Sopenharmony_ci (is_topmost || is_conservative) ? kTheResult + kTopOfStackPadding : 0; 26101cb0ef41Sopenharmony_ci 26111cb0ef41Sopenharmony_ci frame_size_in_bytes_ = 26121cb0ef41Sopenharmony_ci kSystemPointerSize * (stack_parameter_count_ + stack_param_pad_count + 26131cb0ef41Sopenharmony_ci allocatable_register_count + padding_slot_count + 26141cb0ef41Sopenharmony_ci push_result_count) + 26151cb0ef41Sopenharmony_ci BuiltinContinuationFrameConstants::kFixedFrameSize; 26161cb0ef41Sopenharmony_ci 26171cb0ef41Sopenharmony_ci frame_size_in_bytes_above_fp_ = 26181cb0ef41Sopenharmony_ci kSystemPointerSize * (allocatable_register_count + padding_slot_count + 26191cb0ef41Sopenharmony_ci push_result_count) + 26201cb0ef41Sopenharmony_ci (BuiltinContinuationFrameConstants::kFixedFrameSize - 26211cb0ef41Sopenharmony_ci BuiltinContinuationFrameConstants::kFixedFrameSizeAboveFp); 26221cb0ef41Sopenharmony_ci} 26231cb0ef41Sopenharmony_ci 26241cb0ef41Sopenharmony_ci} // namespace internal 26251cb0ef41Sopenharmony_ci} // namespace v8 2626