1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_EXECUTION_FRAMES_H_ 6 #define V8_EXECUTION_FRAMES_H_ 7 8 #include "include/v8-initialization.h" 9 #include "src/base/bounds.h" 10 #include "src/codegen/safepoint-table.h" 11 #include "src/common/globals.h" 12 #include "src/handles/handles.h" 13 #include "src/objects/code.h" 14 #include "src/objects/objects.h" 15 16 // 17 // Frame inheritance hierarchy (please keep in sync with frame-constants.h): 18 // - CommonFrame 19 // - CommonFrameWithJSLinkage 20 // - JavaScriptFrame (aka StandardFrame) 21 // - UnoptimizedFrame 22 // - InterpretedFrame 23 // - BaselineFrame 24 // - OptimizedFrame 25 // - TypedFrameWithJSLinkage 26 // - BuiltinFrame 27 // - JavaScriptBuiltinContinuationFrame 28 // - JavaScriptBuiltinContinuationWithCatchFrame 29 // - TypedFrame 30 // - NativeFrame 31 // - EntryFrame 32 // - ConstructEntryFrame 33 // - ExitFrame 34 // - BuiltinExitFrame 35 // - StubFrame 36 // - JsToWasmFrame 37 // - CWasmEntryFrame 38 // - Internal 39 // - ConstructFrame 40 // - BuiltinContinuationFrame 41 // - WasmFrame 42 // - WasmExitFrame 43 // - WasmDebugBreakFrame 44 // - WasmCompileLazyFrame 45 // 46 47 namespace v8 { 48 namespace internal { 49 namespace wasm { 50 class WasmCode; 51 struct JumpBuffer; 52 class StackMemory; 53 } // namespace wasm 54 55 class AbstractCode; 56 class Debug; 57 class ExternalCallbackScope; 58 class InnerPointerToCodeCache; 59 class Isolate; 60 class ObjectVisitor; 61 class Register; 62 class RootVisitor; 63 class StackFrameInfo; 64 class StackFrameIteratorBase; 65 class StringStream; 66 class ThreadLocalTop; 67 class WasmInstanceObject; 68 class WasmModuleObject; 69 70 class StackHandlerConstants : public AllStatic { 71 public: 72 static const int kNextOffset = 0 * kSystemPointerSize; 73 static const int kPaddingOffset = 1 * kSystemPointerSize; 74 75 static const int kSize = kPaddingOffset + kSystemPointerSize; 76 static const int kSlotCount = kSize >> kSystemPointerSizeLog2; 77 }; 78 79 class StackHandler { 80 public: 81 // Get the address of this stack handler. 82 inline Address address() const; 83 84 // Get the next stack handler in the chain. 85 inline StackHandler* next() const; 86 87 // Get the next stack handler, as an Address. This is safe to use even 88 // when the next handler is null. 89 inline Address next_address() const; 90 91 // Conversion support. 92 static inline StackHandler* FromAddress(Address address); 93 94 private: 95 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler); 96 }; 97 98 #define STACK_FRAME_TYPE_LIST(V) \ 99 V(ENTRY, EntryFrame) \ 100 V(CONSTRUCT_ENTRY, ConstructEntryFrame) \ 101 V(EXIT, ExitFrame) \ 102 IF_WASM(V, WASM, WasmFrame) \ 103 IF_WASM(V, WASM_TO_JS, WasmToJsFrame) \ 104 IF_WASM(V, JS_TO_WASM, JsToWasmFrame) \ 105 IF_WASM(V, STACK_SWITCH, StackSwitchFrame) \ 106 IF_WASM(V, WASM_DEBUG_BREAK, WasmDebugBreakFrame) \ 107 IF_WASM(V, C_WASM_ENTRY, CWasmEntryFrame) \ 108 IF_WASM(V, WASM_EXIT, WasmExitFrame) \ 109 IF_WASM(V, WASM_COMPILE_LAZY, WasmCompileLazyFrame) \ 110 V(INTERPRETED, InterpretedFrame) \ 111 V(BASELINE, BaselineFrame) \ 112 V(OPTIMIZED, OptimizedFrame) \ 113 V(STUB, StubFrame) \ 114 V(BUILTIN_CONTINUATION, BuiltinContinuationFrame) \ 115 V(JAVA_SCRIPT_BUILTIN_CONTINUATION, JavaScriptBuiltinContinuationFrame) \ 116 V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH, \ 117 JavaScriptBuiltinContinuationWithCatchFrame) \ 118 V(INTERNAL, InternalFrame) \ 119 V(CONSTRUCT, ConstructFrame) \ 120 V(BUILTIN, BuiltinFrame) \ 121 V(BUILTIN_EXIT, BuiltinExitFrame) \ 122 V(NATIVE, NativeFrame) 123 124 // Abstract base class for all stack frames. 125 class StackFrame { 126 public: 127 #define DECLARE_TYPE(type, ignore) type, 128 enum Type { 129 NO_FRAME_TYPE = 0, 130 STACK_FRAME_TYPE_LIST(DECLARE_TYPE) NUMBER_OF_TYPES, 131 // Used by FrameScope to indicate that the stack frame is constructed 132 // manually and the FrameScope does not need to emit code. 133 MANUAL 134 }; 135 #undef DECLARE_TYPE 136 137 // Used to mark the outermost JS entry frame. 138 // 139 // The mark is an opaque value that should be pushed onto the stack directly, 140 // carefully crafted to not be interpreted as a tagged pointer. 141 enum JsFrameMarker { 142 INNER_JSENTRY_FRAME = (0 << kSmiTagSize) | kSmiTag, 143 OUTERMOST_JSENTRY_FRAME = (1 << kSmiTagSize) | kSmiTag 144 }; 145 STATIC_ASSERT((INNER_JSENTRY_FRAME & kHeapObjectTagMask) != kHeapObjectTag); 146 STATIC_ASSERT((OUTERMOST_JSENTRY_FRAME & kHeapObjectTagMask) != 147 kHeapObjectTag); 148 149 struct State { 150 Address sp = kNullAddress; 151 Address fp = kNullAddress; 152 Address* pc_address = nullptr; 153 Address callee_fp = kNullAddress; 154 Address* callee_pc_address = nullptr; 155 Address* constant_pool_address = nullptr; 156 }; 157 158 // Convert a stack frame type to a marker that can be stored on the stack. 159 // 160 // The marker is an opaque value, not intended to be interpreted in any way 161 // except being checked by IsTypeMarker or converted by MarkerToType. 162 // It has the same tagging as Smis, so any marker value that does not pass 163 // IsTypeMarker can instead be interpreted as a tagged pointer. 164 // 165 // Note that the marker is not a Smi: Smis on 64-bit architectures are stored 166 // in the top 32 bits of a 64-bit value, which in turn makes them expensive 167 // (in terms of code/instruction size) to push as immediates onto the stack. TypeToMarker(Type type)168 static int32_t TypeToMarker(Type type) { 169 DCHECK_GE(type, 0); 170 return (type << kSmiTagSize) | kSmiTag; 171 } 172 173 // Convert a marker back to a stack frame type. 174 // 175 // Unlike the return value of TypeToMarker, this takes an intptr_t, as that is 176 // the type of the value on the stack. MarkerToType(intptr_t marker)177 static Type MarkerToType(intptr_t marker) { 178 DCHECK(IsTypeMarker(marker)); 179 intptr_t type = marker >> kSmiTagSize; 180 // TODO(petermarshall): There is a bug in the arm simulators that causes 181 // invalid frame markers. 182 #if (defined(USE_SIMULATOR) && \ 183 (V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM)) || \ 184 V8_TARGET_ARCH_RISCV64 185 if (static_cast<uintptr_t>(type) >= Type::NUMBER_OF_TYPES) { 186 // Appease UBSan. 187 return Type::NUMBER_OF_TYPES; 188 } 189 #else 190 DCHECK_LT(static_cast<uintptr_t>(type), Type::NUMBER_OF_TYPES); 191 #endif 192 return static_cast<Type>(type); 193 } 194 195 // Check if a marker is a stack frame type marker or a tagged pointer. 196 // 197 // Returns true if the given marker is tagged as a stack frame type marker, 198 // and should be converted back to a stack frame type using MarkerToType. 199 // Otherwise, the value is a tagged function pointer. IsTypeMarker(intptr_t function_or_marker)200 static bool IsTypeMarker(intptr_t function_or_marker) { 201 return (function_or_marker & kSmiTagMask) == kSmiTag; 202 } 203 204 // Copy constructor; it breaks the connection to host iterator 205 // (as an iterator usually lives on stack). StackFrame(const StackFrame & original)206 StackFrame(const StackFrame& original) V8_NOEXCEPT { 207 this->state_ = original.state_; 208 this->iterator_ = nullptr; 209 this->isolate_ = original.isolate_; 210 } 211 212 // Type testers. is_entry()213 bool is_entry() const { return type() == ENTRY; } is_construct_entry()214 bool is_construct_entry() const { return type() == CONSTRUCT_ENTRY; } is_exit()215 bool is_exit() const { return type() == EXIT; } is_optimized()216 bool is_optimized() const { return type() == OPTIMIZED; } is_unoptimized()217 bool is_unoptimized() const { 218 STATIC_ASSERT(BASELINE == INTERPRETED + 1); 219 return base::IsInRange(type(), INTERPRETED, BASELINE); 220 } is_interpreted()221 bool is_interpreted() const { return type() == INTERPRETED; } is_baseline()222 bool is_baseline() const { return type() == BASELINE; } 223 #if V8_ENABLE_WEBASSEMBLY is_wasm()224 bool is_wasm() const { return this->type() == WASM; } is_c_wasm_entry()225 bool is_c_wasm_entry() const { return type() == C_WASM_ENTRY; } is_wasm_compile_lazy()226 bool is_wasm_compile_lazy() const { return type() == WASM_COMPILE_LAZY; } is_wasm_debug_break()227 bool is_wasm_debug_break() const { return type() == WASM_DEBUG_BREAK; } is_wasm_to_js()228 bool is_wasm_to_js() const { return type() == WASM_TO_JS; } is_js_to_wasm()229 bool is_js_to_wasm() const { return type() == JS_TO_WASM; } 230 #endif // V8_ENABLE_WEBASSEMBLY is_builtin()231 bool is_builtin() const { return type() == BUILTIN; } is_internal()232 bool is_internal() const { return type() == INTERNAL; } is_builtin_continuation()233 bool is_builtin_continuation() const { 234 return type() == BUILTIN_CONTINUATION; 235 } is_java_script_builtin_continuation()236 bool is_java_script_builtin_continuation() const { 237 return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION; 238 } is_java_script_builtin_with_catch_continuation()239 bool is_java_script_builtin_with_catch_continuation() const { 240 return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH; 241 } is_construct()242 bool is_construct() const { return type() == CONSTRUCT; } is_builtin_exit()243 bool is_builtin_exit() const { return type() == BUILTIN_EXIT; } 244 IsJavaScript(Type t)245 static bool IsJavaScript(Type t) { 246 STATIC_ASSERT(INTERPRETED + 1 == BASELINE); 247 STATIC_ASSERT(BASELINE + 1 == OPTIMIZED); 248 return t >= INTERPRETED && t <= OPTIMIZED; 249 } is_java_script()250 bool is_java_script() const { return IsJavaScript(type()); } 251 252 // Accessors. sp()253 Address sp() const { return state_.sp; } fp()254 Address fp() const { return state_.fp; } callee_fp()255 Address callee_fp() const { return state_.callee_fp; } 256 inline Address callee_pc() const; caller_sp()257 Address caller_sp() const { return GetCallerStackPointer(); } 258 inline Address pc() const; 259 260 // Skip authentication of the PC, when using CFI. Used in the profiler, where 261 // in certain corner-cases we do not use an address on the stack, which would 262 // be signed, as the PC of the frame. 263 inline Address unauthenticated_pc() const; 264 constant_pool()265 Address constant_pool() const { return *constant_pool_address(); } set_constant_pool(Address constant_pool)266 void set_constant_pool(Address constant_pool) { 267 *constant_pool_address() = constant_pool; 268 } 269 pc_address()270 Address* pc_address() const { return state_.pc_address; } 271 constant_pool_address()272 Address* constant_pool_address() const { 273 return state_.constant_pool_address; 274 } 275 276 // Get the id of this stack frame. id()277 StackFrameId id() const { return static_cast<StackFrameId>(caller_sp()); } 278 279 // Get the top handler from the current stack iterator. 280 inline StackHandler* top_handler() const; 281 282 // Get the type of this frame. 283 virtual Type type() const = 0; 284 285 // Get the code associated with this frame. 286 // This method could be called during marking phase of GC. 287 virtual Code unchecked_code() const = 0; 288 289 // Search for the code associated with this frame. 290 V8_EXPORT_PRIVATE Code LookupCode() const; 291 292 virtual void Iterate(RootVisitor* v) const = 0; 293 void IteratePc(RootVisitor* v, Address* pc_address, 294 Address* constant_pool_address, Code holder) const; 295 296 // Sets a callback function for return-address rewriting profilers 297 // to resolve the location of a return address to the location of the 298 // profiler's stashed return address. 299 static void SetReturnAddressLocationResolver( 300 ReturnAddressLocationResolver resolver); 301 302 static inline Address ReadPC(Address* pc_address); 303 304 // Resolves pc_address through the resolution address function if one is set. 305 static inline Address* ResolveReturnAddressLocation(Address* pc_address); 306 307 // Printing support. 308 enum PrintMode { OVERVIEW, DETAILS }; 309 virtual void Print(StringStream* accumulator, PrintMode mode, 310 int index) const; 311 isolate()312 Isolate* isolate() const { return isolate_; } 313 314 void operator=(const StackFrame& original) = delete; 315 316 protected: 317 inline explicit StackFrame(StackFrameIteratorBase* iterator); 318 virtual ~StackFrame() = default; 319 320 // Compute the stack pointer for the calling frame. 321 virtual Address GetCallerStackPointer() const = 0; 322 323 // Compute the stack frame type for the given state. 324 static Type ComputeType(const StackFrameIteratorBase* iterator, State* state); 325 326 #ifdef DEBUG 327 bool can_access_heap_objects() const; 328 #endif 329 330 private: 331 const StackFrameIteratorBase* iterator_; 332 Isolate* isolate_; 333 State state_; 334 335 static ReturnAddressLocationResolver return_address_location_resolver_; 336 337 // Fill in the state of the calling frame. 338 virtual void ComputeCallerState(State* state) const = 0; 339 340 // Get the type and the state of the calling frame. 341 virtual Type GetCallerState(State* state) const; 342 343 static const intptr_t kIsolateTag = 1; 344 345 friend class StackFrameIterator; 346 friend class StackFrameIteratorBase; 347 friend class StackHandlerIterator; 348 friend class SafeStackFrameIterator; 349 }; 350 351 class CommonFrame; 352 353 class V8_EXPORT_PRIVATE FrameSummary { 354 public: 355 // Subclasses for the different summary kinds: 356 #define FRAME_SUMMARY_VARIANTS(F) \ 357 F(JAVA_SCRIPT, JavaScriptFrameSummary, java_script_summary_, JavaScript) \ 358 IF_WASM(F, WASM, WasmFrameSummary, wasm_summary_, Wasm) 359 360 #define FRAME_SUMMARY_KIND(kind, type, field, desc) kind, 361 enum Kind { FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_KIND) }; 362 #undef FRAME_SUMMARY_KIND 363 364 class FrameSummaryBase { 365 public: FrameSummaryBase(Isolate * isolate,Kind kind)366 FrameSummaryBase(Isolate* isolate, Kind kind) 367 : isolate_(isolate), kind_(kind) {} isolate()368 Isolate* isolate() const { return isolate_; } kind()369 Kind kind() const { return kind_; } 370 371 private: 372 Isolate* isolate_; 373 Kind kind_; 374 }; 375 376 class JavaScriptFrameSummary : public FrameSummaryBase { 377 public: 378 JavaScriptFrameSummary(Isolate* isolate, Object receiver, 379 JSFunction function, AbstractCode abstract_code, 380 int code_offset, bool is_constructor, 381 FixedArray parameters); 382 383 void EnsureSourcePositionsAvailable(); 384 bool AreSourcePositionsAvailable() const; 385 receiver()386 Handle<Object> receiver() const { return receiver_; } function()387 Handle<JSFunction> function() const { return function_; } abstract_code()388 Handle<AbstractCode> abstract_code() const { return abstract_code_; } code_offset()389 int code_offset() const { return code_offset_; } is_constructor()390 bool is_constructor() const { return is_constructor_; } parameters()391 Handle<FixedArray> parameters() const { return parameters_; } 392 bool is_subject_to_debugging() const; 393 int SourcePosition() const; 394 int SourceStatementPosition() const; 395 Handle<Object> script() const; 396 Handle<Context> native_context() const; 397 Handle<StackFrameInfo> CreateStackFrameInfo() const; 398 399 private: 400 Handle<Object> receiver_; 401 Handle<JSFunction> function_; 402 Handle<AbstractCode> abstract_code_; 403 int code_offset_; 404 bool is_constructor_; 405 Handle<FixedArray> parameters_; 406 }; 407 408 #if V8_ENABLE_WEBASSEMBLY 409 class WasmFrameSummary : public FrameSummaryBase { 410 public: 411 WasmFrameSummary(Isolate*, Handle<WasmInstanceObject>, wasm::WasmCode*, 412 int code_offset, bool at_to_number_conversion); 413 414 Handle<Object> receiver() const; 415 uint32_t function_index() const; code()416 wasm::WasmCode* code() const { return code_; } code_offset()417 int code_offset() const { return code_offset_; } 418 V8_EXPORT_PRIVATE int byte_offset() const; is_constructor()419 bool is_constructor() const { return false; } is_subject_to_debugging()420 bool is_subject_to_debugging() const { return true; } 421 int SourcePosition() const; SourceStatementPosition()422 int SourceStatementPosition() const { return SourcePosition(); } 423 Handle<Script> script() const; wasm_instance()424 Handle<WasmInstanceObject> wasm_instance() const { return wasm_instance_; } 425 Handle<Context> native_context() const; at_to_number_conversion()426 bool at_to_number_conversion() const { return at_to_number_conversion_; } 427 Handle<StackFrameInfo> CreateStackFrameInfo() const; 428 429 private: 430 Handle<WasmInstanceObject> wasm_instance_; 431 bool at_to_number_conversion_; 432 wasm::WasmCode* const code_; 433 int code_offset_; 434 }; 435 #endif // V8_ENABLE_WEBASSEMBLY 436 437 #define FRAME_SUMMARY_CONS(kind, type, field, desc) \ 438 FrameSummary(type summ) : field(summ) {} // NOLINT 439 FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CONS) 440 #undef FRAME_SUMMARY_CONS 441 442 ~FrameSummary(); 443 444 static FrameSummary GetTop(const CommonFrame* frame); 445 static FrameSummary GetBottom(const CommonFrame* frame); 446 static FrameSummary GetSingle(const CommonFrame* frame); 447 static FrameSummary Get(const CommonFrame* frame, int index); 448 449 void EnsureSourcePositionsAvailable(); 450 bool AreSourcePositionsAvailable() const; 451 452 // Dispatched accessors. 453 Handle<Object> receiver() const; 454 int code_offset() const; 455 bool is_constructor() const; 456 bool is_subject_to_debugging() const; 457 Handle<Object> script() const; 458 int SourcePosition() const; 459 int SourceStatementPosition() const; 460 Handle<Context> native_context() const; 461 Handle<StackFrameInfo> CreateStackFrameInfo() const; 462 463 #define FRAME_SUMMARY_CAST(kind_, type, field, desc) \ 464 bool Is##desc() const { return base_.kind() == kind_; } \ 465 const type& As##desc() const { \ 466 DCHECK_EQ(base_.kind(), kind_); \ 467 return field; \ 468 } 469 FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CAST) 470 #undef FRAME_SUMMARY_CAST 471 472 private: 473 #define FRAME_SUMMARY_FIELD(kind, type, field, desc) type field; 474 union { 475 FrameSummaryBase base_; 476 FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_FIELD) 477 }; 478 #undef FRAME_SUMMARY_FIELD 479 }; 480 481 class CommonFrame : public StackFrame { 482 public: 483 // Accessors. 484 virtual Object context() 485 const; // TODO(victorgomes): CommonFrames don't have context. 486 virtual int position() const; 487 488 // Access the expressions in the stack frame including locals. 489 inline Object GetExpression(int index) const; 490 inline void SetExpression(int index, Object value); 491 int ComputeExpressionsCount() const; 492 493 Address GetCallerStackPointer() const override; 494 495 // Build a list with summaries for this frame including all inlined frames. 496 // The functions are ordered bottom-to-top (i.e. summaries.last() is the 497 // top-most activation; caller comes before callee). 498 virtual void Summarize(std::vector<FrameSummary>* frames) const; 499 cast(StackFrame * frame)500 static CommonFrame* cast(StackFrame* frame) { 501 // It is always safe to cast to common. 502 return static_cast<CommonFrame*>(frame); 503 } 504 505 protected: 506 inline explicit CommonFrame(StackFrameIteratorBase* iterator); 507 508 void ComputeCallerState(State* state) const override; 509 510 // Accessors. 511 inline Address caller_fp() const; 512 inline Address caller_pc() const; 513 514 // Computes the address of the PC field in the standard frame given 515 // by the provided frame pointer. 516 static inline Address ComputePCAddress(Address fp); 517 518 // Computes the address of the constant pool field in the standard 519 // frame given by the provided frame pointer. 520 static inline Address ComputeConstantPoolAddress(Address fp); 521 522 // Iterate over expression stack including stack handlers, locals, 523 // and parts of the fixed part including context and code fields. 524 void IterateExpressions(RootVisitor* v) const; 525 526 // Returns the address of the n'th expression stack element. 527 virtual Address GetExpressionAddress(int n) const; 528 529 // Used by OptimizedFrames and StubFrames. 530 void IterateCompiledFrame(RootVisitor* v) const; 531 532 private: 533 friend class StackFrame; 534 friend class SafeStackFrameIterator; 535 }; 536 537 class TypedFrame : public CommonFrame { 538 public: unchecked_code()539 Code unchecked_code() const override { return {}; } Iterate(RootVisitor * v)540 void Iterate(RootVisitor* v) const override { IterateCompiledFrame(v); } 541 542 protected: 543 inline explicit TypedFrame(StackFrameIteratorBase* iterator); 544 }; 545 546 class CommonFrameWithJSLinkage : public CommonFrame { 547 public: 548 // Accessors. 549 virtual JSFunction function() const = 0; 550 551 // Access the parameters. 552 virtual Object receiver() const; 553 virtual Object GetParameter(int index) const; 554 virtual int ComputeParametersCount() const; 555 Handle<FixedArray> GetParameters() const; 556 virtual int GetActualArgumentCount() const; 557 558 // Determine the code for the frame. 559 Code unchecked_code() const override; 560 561 // Lookup exception handler for current {pc}, returns -1 if none found. Also 562 // returns data associated with the handler site specific to the frame type: 563 // - OptimizedFrame : Data is not used and will not return a value. 564 // - UnoptimizedFrame: Data is the register index holding the context. 565 virtual int LookupExceptionHandlerInTable( 566 int* data, HandlerTable::CatchPrediction* prediction); 567 568 // Check if this frame is a constructor frame invoked through 'new'. 569 virtual bool IsConstructor() const; 570 571 // Summarize Frame 572 void Summarize(std::vector<FrameSummary>* frames) const override; 573 574 protected: 575 inline explicit CommonFrameWithJSLinkage(StackFrameIteratorBase* iterator); 576 577 // Determines if the standard frame for the given frame pointer is a 578 // construct frame. 579 static inline bool IsConstructFrame(Address fp); 580 inline Address GetParameterSlot(int index) const; 581 }; 582 583 class TypedFrameWithJSLinkage : public CommonFrameWithJSLinkage { 584 public: 585 void Iterate(RootVisitor* v) const override; 586 587 protected: 588 inline explicit TypedFrameWithJSLinkage(StackFrameIteratorBase* iterator); 589 }; 590 591 class JavaScriptFrame : public CommonFrameWithJSLinkage { 592 public: 593 Type type() const override = 0; 594 595 // Accessors. 596 JSFunction function() const override; 597 Object unchecked_function() const; 598 Script script() const; 599 Object context() const override; 600 int GetActualArgumentCount() const override; 601 602 inline void set_receiver(Object value); 603 604 // Debugger access. 605 void SetParameterValue(int index, Object value) const; 606 607 // Check if this frame is a constructor frame invoked through 'new'. 608 bool IsConstructor() const override; 609 610 // Determines whether this frame includes inlined activations. To get details 611 // about the inlined frames use {GetFunctions} and {Summarize}. 612 bool HasInlinedFrames() const; 613 614 // Garbage collection support. 615 void Iterate(RootVisitor* v) const override; 616 617 // Printing support. 618 void Print(StringStream* accumulator, PrintMode mode, 619 int index) const override; 620 621 // Return a list with {SharedFunctionInfo} objects of this frame. 622 virtual void GetFunctions(std::vector<SharedFunctionInfo>* functions) const; 623 624 void GetFunctions(std::vector<Handle<SharedFunctionInfo>>* functions) const; 625 626 // Architecture-specific register description. 627 static Register fp_register(); 628 static Register context_register(); 629 static Register constant_pool_pointer_register(); 630 cast(StackFrame * frame)631 static JavaScriptFrame* cast(StackFrame* frame) { 632 DCHECK(frame->is_java_script()); 633 return static_cast<JavaScriptFrame*>(frame); 634 } 635 636 static void PrintFunctionAndOffset(JSFunction function, AbstractCode code, 637 int code_offset, FILE* file, 638 bool print_line_number); 639 640 static void PrintTop(Isolate* isolate, FILE* file, bool print_args, 641 bool print_line_number); 642 643 static void CollectFunctionAndOffsetForICStats(JSFunction function, 644 AbstractCode code, 645 int code_offset); 646 647 protected: 648 inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator); 649 650 Address GetCallerStackPointer() const override; 651 PrintFrameKind(StringStream * accumulator)652 virtual void PrintFrameKind(StringStream* accumulator) const {} 653 654 private: 655 inline Object function_slot_object() const; 656 657 friend class StackFrameIteratorBase; 658 }; 659 660 class NativeFrame : public TypedFrame { 661 public: type()662 Type type() const override { return NATIVE; } 663 664 // Garbage collection support. Iterate(RootVisitor * v)665 void Iterate(RootVisitor* v) const override {} 666 667 protected: 668 inline explicit NativeFrame(StackFrameIteratorBase* iterator); 669 670 private: 671 void ComputeCallerState(State* state) const override; 672 673 friend class StackFrameIteratorBase; 674 }; 675 676 // Entry frames are used to enter JavaScript execution from C. 677 class EntryFrame : public TypedFrame { 678 public: type()679 Type type() const override { return ENTRY; } 680 681 Code unchecked_code() const override; 682 683 // Garbage collection support. 684 void Iterate(RootVisitor* v) const override; 685 cast(StackFrame * frame)686 static EntryFrame* cast(StackFrame* frame) { 687 DCHECK(frame->is_entry()); 688 return static_cast<EntryFrame*>(frame); 689 } 690 691 protected: 692 inline explicit EntryFrame(StackFrameIteratorBase* iterator); 693 694 // The caller stack pointer for entry frames is always zero. The 695 // real information about the caller frame is available through the 696 // link to the top exit frame. GetCallerStackPointer()697 Address GetCallerStackPointer() const override { return 0; } 698 699 private: 700 void ComputeCallerState(State* state) const override; 701 Type GetCallerState(State* state) const override; 702 703 friend class StackFrameIteratorBase; 704 }; 705 706 class ConstructEntryFrame : public EntryFrame { 707 public: type()708 Type type() const override { return CONSTRUCT_ENTRY; } 709 710 Code unchecked_code() const override; 711 cast(StackFrame * frame)712 static ConstructEntryFrame* cast(StackFrame* frame) { 713 DCHECK(frame->is_construct_entry()); 714 return static_cast<ConstructEntryFrame*>(frame); 715 } 716 717 protected: 718 inline explicit ConstructEntryFrame(StackFrameIteratorBase* iterator); 719 720 private: 721 friend class StackFrameIteratorBase; 722 }; 723 724 // Exit frames are used to exit JavaScript execution and go to C, or to switch 725 // out of the current stack for wasm stack-switching. 726 class ExitFrame : public TypedFrame { 727 public: type()728 Type type() const override { return EXIT; } 729 730 // Garbage collection support. 731 void Iterate(RootVisitor* v) const override; 732 cast(StackFrame * frame)733 static ExitFrame* cast(StackFrame* frame) { 734 DCHECK(frame->is_exit()); 735 return static_cast<ExitFrame*>(frame); 736 } 737 738 // Compute the state and type of an exit frame given a frame 739 // pointer. Used when constructing the first stack frame seen by an 740 // iterator and the frames following entry frames. 741 static Type GetStateForFramePointer(Address fp, State* state); 742 static Address ComputeStackPointer(Address fp); 743 static StackFrame::Type ComputeFrameType(Address fp); 744 static void FillState(Address fp, Address sp, State* state); 745 746 protected: 747 inline explicit ExitFrame(StackFrameIteratorBase* iterator); 748 749 private: 750 void ComputeCallerState(State* state) const override; 751 752 friend class StackFrameIteratorBase; 753 }; 754 755 // Builtin exit frames are a special case of exit frames, which are used 756 // whenever C++ builtins (e.g., Math.acos) are called. Their main purpose is 757 // to allow such builtins to appear in stack traces. 758 class BuiltinExitFrame : public ExitFrame { 759 public: type()760 Type type() const override { return BUILTIN_EXIT; } 761 762 JSFunction function() const; 763 764 Object receiver() const; 765 Object GetParameter(int i) const; 766 int ComputeParametersCount() const; 767 Handle<FixedArray> GetParameters() const; 768 769 // Check if this frame is a constructor frame invoked through 'new'. 770 bool IsConstructor() const; 771 772 void Print(StringStream* accumulator, PrintMode mode, 773 int index) const override; 774 775 // Summarize Frame 776 void Summarize(std::vector<FrameSummary>* frames) const override; 777 778 protected: 779 inline explicit BuiltinExitFrame(StackFrameIteratorBase* iterator); 780 781 private: 782 inline Object receiver_slot_object() const; 783 inline Object argc_slot_object() const; 784 inline Object target_slot_object() const; 785 inline Object new_target_slot_object() const; 786 787 friend class StackFrameIteratorBase; 788 }; 789 790 class StubFrame : public TypedFrame { 791 public: type()792 Type type() const override { return STUB; } 793 794 // Determine the code for the frame. 795 Code unchecked_code() const override; 796 797 // Lookup exception handler for current {pc}, returns -1 if none found. Only 798 // TurboFan stub frames are supported. 799 int LookupExceptionHandlerInTable(); 800 801 protected: 802 inline explicit StubFrame(StackFrameIteratorBase* iterator); 803 804 private: 805 friend class StackFrameIteratorBase; 806 }; 807 808 class OptimizedFrame : public JavaScriptFrame { 809 public: type()810 Type type() const override { return OPTIMIZED; } 811 812 // GC support. 813 void Iterate(RootVisitor* v) const override; 814 815 // Return a list with {SharedFunctionInfo} objects of this frame. 816 // The functions are ordered bottom-to-top (i.e. functions.last() 817 // is the top-most activation) 818 void GetFunctions(std::vector<SharedFunctionInfo>* functions) const override; 819 820 void Summarize(std::vector<FrameSummary>* frames) const override; 821 822 // Lookup exception handler for current {pc}, returns -1 if none found. 823 int LookupExceptionHandlerInTable( 824 int* data, HandlerTable::CatchPrediction* prediction) override; 825 826 DeoptimizationData GetDeoptimizationData(int* deopt_index) const; 827 828 int ComputeParametersCount() const override; 829 830 static int StackSlotOffsetRelativeToFp(int slot_index); 831 832 protected: 833 inline explicit OptimizedFrame(StackFrameIteratorBase* iterator); 834 835 private: 836 friend class StackFrameIteratorBase; 837 838 Object StackSlotAt(int index) const; 839 }; 840 841 // An unoptimized frame is a JavaScript frame that is executing bytecode. It 842 // may be executing it using the interpreter, or via baseline code compiled from 843 // the bytecode. 844 class UnoptimizedFrame : public JavaScriptFrame { 845 public: 846 // Accessors. 847 int position() const override; 848 849 // Lookup exception handler for current {pc}, returns -1 if none found. 850 int LookupExceptionHandlerInTable( 851 int* data, HandlerTable::CatchPrediction* prediction) override; 852 853 // Returns the current offset into the bytecode stream. 854 virtual int GetBytecodeOffset() const = 0; 855 856 // Returns the frame's current bytecode array. 857 BytecodeArray GetBytecodeArray() const; 858 859 // Access to the interpreter register file for this frame. 860 Object ReadInterpreterRegister(int register_index) const; 861 862 // Build a list with summaries for this frame including all inlined frames. 863 void Summarize(std::vector<FrameSummary>* frames) const override; 864 cast(StackFrame * frame)865 static UnoptimizedFrame* cast(StackFrame* frame) { 866 DCHECK(frame->is_unoptimized()); 867 return static_cast<UnoptimizedFrame*>(frame); 868 } 869 870 protected: 871 inline explicit UnoptimizedFrame(StackFrameIteratorBase* iterator); 872 873 Address GetExpressionAddress(int n) const override; 874 875 private: 876 friend class StackFrameIteratorBase; 877 }; 878 879 class InterpretedFrame : public UnoptimizedFrame { 880 public: type()881 Type type() const override { return INTERPRETED; } 882 883 // Returns the current offset into the bytecode stream. 884 int GetBytecodeOffset() const override; 885 886 // Updates the current offset into the bytecode stream, mainly used for stack 887 // unwinding to continue execution at a different bytecode offset. 888 void PatchBytecodeOffset(int new_offset); 889 890 // Updates the frame's BytecodeArray with |bytecode_array|. Used by the 891 // debugger to swap execution onto a BytecodeArray patched with breakpoints. 892 void PatchBytecodeArray(BytecodeArray bytecode_array); 893 cast(StackFrame * frame)894 static InterpretedFrame* cast(StackFrame* frame) { 895 DCHECK(frame->is_interpreted()); 896 return static_cast<InterpretedFrame*>(frame); 897 } cast(const StackFrame * frame)898 static const InterpretedFrame* cast(const StackFrame* frame) { 899 DCHECK(frame->is_interpreted()); 900 return static_cast<const InterpretedFrame*>(frame); 901 } 902 903 static int GetBytecodeOffset(Address fp); 904 905 protected: 906 inline explicit InterpretedFrame(StackFrameIteratorBase* iterator); 907 908 private: 909 friend class StackFrameIteratorBase; 910 }; 911 912 class BaselineFrame : public UnoptimizedFrame { 913 public: type()914 Type type() const override { return BASELINE; } 915 916 // Returns the current offset into the bytecode stream. 917 int GetBytecodeOffset() const override; 918 919 intptr_t GetPCForBytecodeOffset(int lookup_offset) const; 920 921 void PatchContext(Context value); 922 cast(StackFrame * frame)923 static BaselineFrame* cast(StackFrame* frame) { 924 DCHECK(frame->is_baseline()); 925 return static_cast<BaselineFrame*>(frame); 926 } 927 928 protected: 929 inline explicit BaselineFrame(StackFrameIteratorBase* iterator); 930 931 private: 932 friend class StackFrameIteratorBase; 933 }; 934 935 // Builtin frames are built for builtins with JavaScript linkage, such as 936 // various standard library functions (i.e. Math.asin, Math.floor, etc.). 937 class BuiltinFrame final : public TypedFrameWithJSLinkage { 938 public: type()939 Type type() const final { return BUILTIN; } 940 cast(StackFrame * frame)941 static BuiltinFrame* cast(StackFrame* frame) { 942 DCHECK(frame->is_builtin()); 943 return static_cast<BuiltinFrame*>(frame); 944 } 945 946 JSFunction function() const override; 947 int ComputeParametersCount() const override; 948 949 protected: 950 inline explicit BuiltinFrame(StackFrameIteratorBase* iterator); 951 952 private: 953 friend class StackFrameIteratorBase; 954 }; 955 956 #if V8_ENABLE_WEBASSEMBLY 957 class WasmFrame : public TypedFrame { 958 public: type()959 Type type() const override { return WASM; } 960 961 // Printing support. 962 void Print(StringStream* accumulator, PrintMode mode, 963 int index) const override; 964 965 // Lookup exception handler for current {pc}, returns -1 if none found. 966 int LookupExceptionHandlerInTable(); 967 968 // Accessors. 969 V8_EXPORT_PRIVATE WasmInstanceObject wasm_instance() const; 970 V8_EXPORT_PRIVATE wasm::NativeModule* native_module() const; 971 wasm::WasmCode* wasm_code() const; 972 int function_index() const; 973 Script script() const; 974 // Byte position in the module, or asm.js source position. 975 int position() const override; 976 Object context() const override; 977 bool at_to_number_conversion() const; 978 // Byte offset in the function. 979 int byte_offset() const; 980 bool is_inspectable() const; 981 982 void Summarize(std::vector<FrameSummary>* frames) const override; 983 cast(StackFrame * frame)984 static WasmFrame* cast(StackFrame* frame) { 985 DCHECK(frame->is_wasm()); 986 return static_cast<WasmFrame*>(frame); 987 } 988 989 protected: 990 inline explicit WasmFrame(StackFrameIteratorBase* iterator); 991 992 private: 993 friend class StackFrameIteratorBase; 994 WasmModuleObject module_object() const; 995 }; 996 997 class WasmExitFrame : public WasmFrame { 998 public: type()999 Type type() const override { return WASM_EXIT; } 1000 static Address ComputeStackPointer(Address fp); 1001 1002 protected: 1003 inline explicit WasmExitFrame(StackFrameIteratorBase* iterator); 1004 1005 private: 1006 friend class StackFrameIteratorBase; 1007 }; 1008 1009 class WasmDebugBreakFrame final : public TypedFrame { 1010 public: type()1011 Type type() const override { return WASM_DEBUG_BREAK; } 1012 1013 // GC support. 1014 void Iterate(RootVisitor* v) const override; 1015 1016 void Print(StringStream* accumulator, PrintMode mode, 1017 int index) const override; 1018 cast(StackFrame * frame)1019 static WasmDebugBreakFrame* cast(StackFrame* frame) { 1020 DCHECK(frame->is_wasm_debug_break()); 1021 return static_cast<WasmDebugBreakFrame*>(frame); 1022 } 1023 1024 protected: 1025 inline explicit WasmDebugBreakFrame(StackFrameIteratorBase*); 1026 1027 private: 1028 friend class StackFrameIteratorBase; 1029 }; 1030 1031 class WasmToJsFrame : public StubFrame { 1032 public: type()1033 Type type() const override { return WASM_TO_JS; } 1034 1035 protected: 1036 inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator); 1037 1038 private: 1039 friend class StackFrameIteratorBase; 1040 }; 1041 1042 class JsToWasmFrame : public StubFrame { 1043 public: type()1044 Type type() const override { return JS_TO_WASM; } 1045 1046 void Iterate(RootVisitor* v) const override; 1047 1048 protected: 1049 inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator); 1050 1051 private: 1052 friend class StackFrameIteratorBase; 1053 }; 1054 1055 class StackSwitchFrame : public ExitFrame { 1056 public: type()1057 Type type() const override { return STACK_SWITCH; } 1058 void Iterate(RootVisitor* v) const override; 1059 static void GetStateForJumpBuffer(wasm::JumpBuffer* jmpbuf, State* state); 1060 1061 protected: 1062 inline explicit StackSwitchFrame(StackFrameIteratorBase* iterator); 1063 1064 private: 1065 friend class StackFrameIteratorBase; 1066 }; 1067 1068 class CWasmEntryFrame : public StubFrame { 1069 public: type()1070 Type type() const override { return C_WASM_ENTRY; } 1071 1072 protected: 1073 inline explicit CWasmEntryFrame(StackFrameIteratorBase* iterator); 1074 1075 private: 1076 friend class StackFrameIteratorBase; 1077 Type GetCallerState(State* state) const override; 1078 }; 1079 1080 class WasmCompileLazyFrame : public TypedFrame { 1081 public: type()1082 Type type() const override { return WASM_COMPILE_LAZY; } 1083 1084 WasmInstanceObject wasm_instance() const; 1085 FullObjectSlot wasm_instance_slot() const; 1086 1087 // Garbage collection support. 1088 void Iterate(RootVisitor* v) const override; 1089 cast(StackFrame * frame)1090 static WasmCompileLazyFrame* cast(StackFrame* frame) { 1091 DCHECK(frame->is_wasm_compile_lazy()); 1092 return static_cast<WasmCompileLazyFrame*>(frame); 1093 } 1094 1095 protected: 1096 inline explicit WasmCompileLazyFrame(StackFrameIteratorBase* iterator); 1097 1098 private: 1099 friend class StackFrameIteratorBase; 1100 }; 1101 #endif // V8_ENABLE_WEBASSEMBLY 1102 1103 class InternalFrame : public TypedFrame { 1104 public: type()1105 Type type() const override { return INTERNAL; } 1106 1107 // Garbage collection support. 1108 void Iterate(RootVisitor* v) const override; 1109 cast(StackFrame * frame)1110 static InternalFrame* cast(StackFrame* frame) { 1111 DCHECK(frame->is_internal()); 1112 return static_cast<InternalFrame*>(frame); 1113 } 1114 1115 protected: 1116 inline explicit InternalFrame(StackFrameIteratorBase* iterator); 1117 1118 private: 1119 friend class StackFrameIteratorBase; 1120 }; 1121 1122 // Construct frames are special trampoline frames introduced to handle 1123 // function invocations through 'new'. 1124 class ConstructFrame : public InternalFrame { 1125 public: type()1126 Type type() const override { return CONSTRUCT; } 1127 cast(StackFrame * frame)1128 static ConstructFrame* cast(StackFrame* frame) { 1129 DCHECK(frame->is_construct()); 1130 return static_cast<ConstructFrame*>(frame); 1131 } 1132 1133 protected: 1134 inline explicit ConstructFrame(StackFrameIteratorBase* iterator); 1135 1136 private: 1137 friend class StackFrameIteratorBase; 1138 }; 1139 1140 class BuiltinContinuationFrame : public InternalFrame { 1141 public: type()1142 Type type() const override { return BUILTIN_CONTINUATION; } 1143 cast(StackFrame * frame)1144 static BuiltinContinuationFrame* cast(StackFrame* frame) { 1145 DCHECK(frame->is_builtin_continuation()); 1146 return static_cast<BuiltinContinuationFrame*>(frame); 1147 } 1148 1149 protected: 1150 inline explicit BuiltinContinuationFrame(StackFrameIteratorBase* iterator); 1151 1152 private: 1153 friend class StackFrameIteratorBase; 1154 }; 1155 1156 class JavaScriptBuiltinContinuationFrame : public TypedFrameWithJSLinkage { 1157 public: type()1158 Type type() const override { return JAVA_SCRIPT_BUILTIN_CONTINUATION; } 1159 cast(StackFrame * frame)1160 static JavaScriptBuiltinContinuationFrame* cast(StackFrame* frame) { 1161 DCHECK(frame->is_java_script_builtin_continuation()); 1162 return static_cast<JavaScriptBuiltinContinuationFrame*>(frame); 1163 } 1164 1165 JSFunction function() const override; 1166 int ComputeParametersCount() const override; 1167 intptr_t GetSPToFPDelta() const; 1168 1169 Object context() const override; 1170 1171 protected: 1172 inline explicit JavaScriptBuiltinContinuationFrame( 1173 StackFrameIteratorBase* iterator); 1174 1175 private: 1176 friend class StackFrameIteratorBase; 1177 }; 1178 1179 class JavaScriptBuiltinContinuationWithCatchFrame 1180 : public JavaScriptBuiltinContinuationFrame { 1181 public: type()1182 Type type() const override { 1183 return JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH; 1184 } 1185 cast(StackFrame * frame)1186 static JavaScriptBuiltinContinuationWithCatchFrame* cast(StackFrame* frame) { 1187 DCHECK(frame->is_java_script_builtin_with_catch_continuation()); 1188 return static_cast<JavaScriptBuiltinContinuationWithCatchFrame*>(frame); 1189 } 1190 1191 // Patch in the exception object at the appropriate location into the stack 1192 // frame. 1193 void SetException(Object exception); 1194 1195 protected: 1196 inline explicit JavaScriptBuiltinContinuationWithCatchFrame( 1197 StackFrameIteratorBase* iterator); 1198 1199 private: 1200 friend class StackFrameIteratorBase; 1201 }; 1202 1203 class StackFrameIteratorBase { 1204 public: 1205 StackFrameIteratorBase(const StackFrameIteratorBase&) = delete; 1206 StackFrameIteratorBase& operator=(const StackFrameIteratorBase&) = delete; 1207 isolate()1208 Isolate* isolate() const { return isolate_; } 1209 done()1210 bool done() const { return frame_ == nullptr; } 1211 1212 protected: 1213 // An iterator that iterates over a given thread's stack. 1214 StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects); 1215 1216 Isolate* isolate_; 1217 #define DECLARE_SINGLETON(ignore, type) type type##_; 1218 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON) 1219 #undef DECLARE_SINGLETON 1220 StackFrame* frame_; 1221 StackHandler* handler_; 1222 const bool can_access_heap_objects_; 1223 handler()1224 StackHandler* handler() const { 1225 DCHECK(!done()); 1226 return handler_; 1227 } 1228 1229 // Get the type-specific frame singleton in a given state. 1230 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state); 1231 // A helper function, can return a nullptr pointer. 1232 StackFrame* SingletonFor(StackFrame::Type type); 1233 1234 private: 1235 friend class StackFrame; 1236 }; 1237 1238 class StackFrameIterator : public StackFrameIteratorBase { 1239 public: 1240 // An iterator that iterates over the isolate's current thread's stack, 1241 V8_EXPORT_PRIVATE explicit StackFrameIterator(Isolate* isolate); 1242 // An iterator that iterates over a given thread's stack. 1243 V8_EXPORT_PRIVATE StackFrameIterator(Isolate* isolate, ThreadLocalTop* t); 1244 #if V8_ENABLE_WEBASSEMBLY 1245 // An iterator that iterates over a given wasm stack segment. 1246 V8_EXPORT_PRIVATE StackFrameIterator(Isolate* isolate, 1247 wasm::StackMemory* stack); 1248 #endif 1249 1250 StackFrameIterator(const StackFrameIterator&) = delete; 1251 StackFrameIterator& operator=(const StackFrameIterator&) = delete; 1252 frame()1253 StackFrame* frame() const { 1254 DCHECK(!done()); 1255 return frame_; 1256 } 1257 V8_EXPORT_PRIVATE void Advance(); 1258 StackFrame* Reframe(); 1259 1260 private: 1261 // Go back to the first frame. 1262 void Reset(ThreadLocalTop* top); 1263 #if V8_ENABLE_WEBASSEMBLY 1264 void Reset(ThreadLocalTop* top, wasm::StackMemory* stack); 1265 #endif 1266 }; 1267 1268 // Iterator that supports iterating through all JavaScript frames. 1269 class JavaScriptFrameIterator { 1270 public: 1271 inline explicit JavaScriptFrameIterator(Isolate* isolate); 1272 inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top); 1273 1274 inline JavaScriptFrame* frame() const; 1275 done()1276 bool done() const { return iterator_.done(); } 1277 V8_EXPORT_PRIVATE void Advance(); AdvanceOneFrame()1278 void AdvanceOneFrame() { iterator_.Advance(); } 1279 inline JavaScriptFrame* Reframe(); 1280 1281 private: 1282 StackFrameIterator iterator_; 1283 }; 1284 1285 // NOTE: The stack trace frame iterator is an iterator that only traverse proper 1286 // JavaScript frames that have proper JavaScript functions and WebAssembly 1287 // frames. 1288 class V8_EXPORT_PRIVATE StackTraceFrameIterator { 1289 public: 1290 explicit StackTraceFrameIterator(Isolate* isolate); 1291 // Skip frames until the frame with the given id is reached. 1292 StackTraceFrameIterator(Isolate* isolate, StackFrameId id); done()1293 bool done() const { return iterator_.done(); } 1294 void Advance(); AdvanceOneFrame()1295 void AdvanceOneFrame() { iterator_.Advance(); } 1296 int FrameFunctionCount() const; 1297 1298 inline CommonFrame* frame() const; 1299 inline CommonFrame* Reframe(); 1300 1301 inline bool is_javascript() const; 1302 #if V8_ENABLE_WEBASSEMBLY 1303 inline bool is_wasm() const; 1304 #endif // V8_ENABLE_WEBASSEMBLY 1305 inline JavaScriptFrame* javascript_frame() const; 1306 1307 // Use this instead of FrameSummary::GetTop(javascript_frame) to keep 1308 // filtering behavior consistent with the rest of StackTraceFrameIterator. 1309 FrameSummary GetTopValidFrame() const; 1310 1311 private: 1312 StackFrameIterator iterator_; 1313 static bool IsValidFrame(StackFrame* frame); 1314 static bool IsValidJSFunction(JSFunction f); 1315 }; 1316 1317 class SafeStackFrameIterator : public StackFrameIteratorBase { 1318 public: 1319 SafeStackFrameIterator(Isolate* isolate, Address pc, Address fp, Address sp, 1320 Address lr, Address js_entry_sp); 1321 1322 inline StackFrame* frame() const; 1323 void Advance(); 1324 top_frame_type()1325 StackFrame::Type top_frame_type() const { return top_frame_type_; } top_context_address()1326 Address top_context_address() const { return top_context_address_; } 1327 1328 private: 1329 void AdvanceOneFrame(); 1330 IsValidStackAddress(Address addr)1331 bool IsValidStackAddress(Address addr) const { 1332 return low_bound_ <= addr && addr <= high_bound_; 1333 } 1334 bool IsValidFrame(StackFrame* frame) const; 1335 bool IsValidCaller(StackFrame* frame); 1336 bool IsValidExitFrame(Address fp) const; 1337 bool IsValidTop(ThreadLocalTop* top) const; 1338 1339 // Returns true if the pc points to a bytecode handler and the frame pointer 1340 // doesn't seem to be a bytecode handler's frame, which implies that the 1341 // bytecode handler has an elided frame. This is not precise and might give 1342 // false negatives since it relies on checks to the frame's type marker, 1343 // which might be uninitialized. 1344 bool IsNoFrameBytecodeHandlerPc(Isolate* isolate, Address pc, 1345 Address fp) const; 1346 1347 const Address low_bound_; 1348 const Address high_bound_; 1349 StackFrame::Type top_frame_type_; 1350 Address top_context_address_; 1351 ExternalCallbackScope* external_callback_scope_; 1352 Address top_link_register_; 1353 }; 1354 1355 // Frame layout helper classes. Used by the deoptimizer and instruction 1356 // selector. 1357 // ------------------------------------------------------------------------- 1358 1359 // How to calculate the frame layout information. Precise, when all information 1360 // is available during deoptimization. Conservative, when an overapproximation 1361 // is fine. 1362 // TODO(jgruber): Investigate whether the conservative kind can be removed. It 1363 // seems possible: 1. is_topmost should be known through the outer_state chain 1364 // of FrameStateDescriptor; 2. the deopt_kind may be a property of the bailout 1365 // id; 3. for continuation_mode, we only care whether it is a mode with catch, 1366 // and that is likewise known at compile-time. 1367 // There is nothing specific blocking this, the investigation just requires time 1368 // and it is not that important to get the exact frame height at compile-time. 1369 enum class FrameInfoKind { 1370 kPrecise, 1371 kConservative, 1372 }; 1373 1374 // Used by the deoptimizer. Corresponds to frame kinds: 1375 enum class BuiltinContinuationMode { 1376 STUB, // BuiltinContinuationFrame 1377 JAVASCRIPT, // JavaScriptBuiltinContinuationFrame 1378 JAVASCRIPT_WITH_CATCH, // JavaScriptBuiltinContinuationWithCatchFrame 1379 JAVASCRIPT_HANDLE_EXCEPTION // JavaScriptBuiltinContinuationWithCatchFrame 1380 }; 1381 1382 class UnoptimizedFrameInfo { 1383 public: Precise(int parameters_count_with_receiver,int translation_height,bool is_topmost,bool pad_arguments)1384 static UnoptimizedFrameInfo Precise(int parameters_count_with_receiver, 1385 int translation_height, bool is_topmost, 1386 bool pad_arguments) { 1387 return {parameters_count_with_receiver, translation_height, is_topmost, 1388 pad_arguments, FrameInfoKind::kPrecise}; 1389 } 1390 Conservative(int parameters_count_with_receiver,int locals_count)1391 static UnoptimizedFrameInfo Conservative(int parameters_count_with_receiver, 1392 int locals_count) { 1393 return {parameters_count_with_receiver, locals_count, false, true, 1394 FrameInfoKind::kConservative}; 1395 } 1396 1397 static uint32_t GetStackSizeForAdditionalArguments(int parameters_count); 1398 register_stack_slot_count()1399 uint32_t register_stack_slot_count() const { 1400 return register_stack_slot_count_; 1401 } frame_size_in_bytes_without_fixed()1402 uint32_t frame_size_in_bytes_without_fixed() const { 1403 return frame_size_in_bytes_without_fixed_; 1404 } frame_size_in_bytes()1405 uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; } 1406 1407 private: 1408 UnoptimizedFrameInfo(int parameters_count_with_receiver, 1409 int translation_height, bool is_topmost, 1410 bool pad_arguments, FrameInfoKind frame_info_kind); 1411 1412 uint32_t register_stack_slot_count_; 1413 uint32_t frame_size_in_bytes_without_fixed_; 1414 uint32_t frame_size_in_bytes_; 1415 }; 1416 1417 class ConstructStubFrameInfo { 1418 public: Precise(int translation_height,bool is_topmost)1419 static ConstructStubFrameInfo Precise(int translation_height, 1420 bool is_topmost) { 1421 return {translation_height, is_topmost, FrameInfoKind::kPrecise}; 1422 } 1423 Conservative(int parameters_count)1424 static ConstructStubFrameInfo Conservative(int parameters_count) { 1425 return {parameters_count, false, FrameInfoKind::kConservative}; 1426 } 1427 frame_size_in_bytes_without_fixed()1428 uint32_t frame_size_in_bytes_without_fixed() const { 1429 return frame_size_in_bytes_without_fixed_; 1430 } frame_size_in_bytes()1431 uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; } 1432 1433 private: 1434 ConstructStubFrameInfo(int translation_height, bool is_topmost, 1435 FrameInfoKind frame_info_kind); 1436 1437 uint32_t frame_size_in_bytes_without_fixed_; 1438 uint32_t frame_size_in_bytes_; 1439 }; 1440 1441 // Used by BuiltinContinuationFrameInfo. 1442 class CallInterfaceDescriptor; 1443 class RegisterConfiguration; 1444 1445 class BuiltinContinuationFrameInfo { 1446 public: Precise(int translation_height,const CallInterfaceDescriptor & continuation_descriptor,const RegisterConfiguration * register_config,bool is_topmost,DeoptimizeKind deopt_kind,BuiltinContinuationMode continuation_mode)1447 static BuiltinContinuationFrameInfo Precise( 1448 int translation_height, 1449 const CallInterfaceDescriptor& continuation_descriptor, 1450 const RegisterConfiguration* register_config, bool is_topmost, 1451 DeoptimizeKind deopt_kind, BuiltinContinuationMode continuation_mode) { 1452 return {translation_height, 1453 continuation_descriptor, 1454 register_config, 1455 is_topmost, 1456 deopt_kind, 1457 continuation_mode, 1458 FrameInfoKind::kPrecise}; 1459 } 1460 Conservative(int parameters_count,const CallInterfaceDescriptor & continuation_descriptor,const RegisterConfiguration * register_config)1461 static BuiltinContinuationFrameInfo Conservative( 1462 int parameters_count, 1463 const CallInterfaceDescriptor& continuation_descriptor, 1464 const RegisterConfiguration* register_config) { 1465 // It doesn't matter what we pass as is_topmost, deopt_kind and 1466 // continuation_mode; these values are ignored in conservative mode. 1467 return {parameters_count, 1468 continuation_descriptor, 1469 register_config, 1470 false, 1471 DeoptimizeKind::kEager, 1472 BuiltinContinuationMode::STUB, 1473 FrameInfoKind::kConservative}; 1474 } 1475 frame_has_result_stack_slot()1476 bool frame_has_result_stack_slot() const { 1477 return frame_has_result_stack_slot_; 1478 } translated_stack_parameter_count()1479 uint32_t translated_stack_parameter_count() const { 1480 return translated_stack_parameter_count_; 1481 } stack_parameter_count()1482 uint32_t stack_parameter_count() const { return stack_parameter_count_; } frame_size_in_bytes()1483 uint32_t frame_size_in_bytes() const { return frame_size_in_bytes_; } frame_size_in_bytes_above_fp()1484 uint32_t frame_size_in_bytes_above_fp() const { 1485 return frame_size_in_bytes_above_fp_; 1486 } 1487 1488 private: 1489 BuiltinContinuationFrameInfo( 1490 int translation_height, 1491 const CallInterfaceDescriptor& continuation_descriptor, 1492 const RegisterConfiguration* register_config, bool is_topmost, 1493 DeoptimizeKind deopt_kind, BuiltinContinuationMode continuation_mode, 1494 FrameInfoKind frame_info_kind); 1495 1496 bool frame_has_result_stack_slot_; 1497 uint32_t translated_stack_parameter_count_; 1498 uint32_t stack_parameter_count_; 1499 uint32_t frame_size_in_bytes_; 1500 uint32_t frame_size_in_bytes_above_fp_; 1501 }; 1502 1503 } // namespace internal 1504 } // namespace v8 1505 1506 #endif // V8_EXECUTION_FRAMES_H_ 1507