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