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