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