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/allocation.h" 9 #include "src/handles.h" 10 #include "src/safepoint-table.h" 11 12 namespace v8 { 13 namespace internal { 14 15 #if V8_TARGET_ARCH_ARM64 16 typedef uint64_t RegList; 17 #else 18 typedef uint32_t RegList; 19 #endif 20 21 // Get the number of registers in a given register list. 22 int NumRegs(RegList list); 23 24 void SetUpJSCallerSavedCodeData(); 25 26 // Return the code of the n-th saved register available to JavaScript. 27 int JSCallerSavedCode(int n); 28 29 30 // Forward declarations. 31 class ExternalCallbackScope; 32 class StackFrameIteratorBase; 33 class ThreadLocalTop; 34 class Isolate; 35 36 class InnerPointerToCodeCache { 37 public: 38 struct InnerPointerToCodeCacheEntry { 39 Address inner_pointer; 40 Code* code; 41 SafepointEntry safepoint_entry; 42 }; 43 InnerPointerToCodeCache(Isolate * isolate)44 explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) { 45 Flush(); 46 } 47 48 Code* GcSafeFindCodeForInnerPointer(Address inner_pointer); 49 Code* GcSafeCastToCode(HeapObject* object, Address inner_pointer); 50 Flush()51 void Flush() { 52 memset(&cache_[0], 0, sizeof(cache_)); 53 } 54 55 InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer); 56 57 private: cache(int index)58 InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; } 59 60 Isolate* isolate_; 61 62 static const int kInnerPointerToCodeCacheSize = 1024; 63 InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize]; 64 65 DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache); 66 }; 67 68 69 // Every try-block pushes the context register. 70 class TryBlockConstant : public AllStatic { 71 public: 72 static const int kElementCount = 1; 73 }; 74 75 76 class StackHandlerConstants : public AllStatic { 77 public: 78 static const int kNextOffset = 0 * kPointerSize; 79 80 static const int kSize = kNextOffset + kPointerSize; 81 static const int kSlotCount = kSize >> kPointerSizeLog2; 82 }; 83 84 85 class StackHandler BASE_EMBEDDED { 86 public: 87 // Get the address of this stack handler. 88 inline Address address() const; 89 90 // Get the next stack handler in the chain. 91 inline StackHandler* next() const; 92 93 // Conversion support. 94 static inline StackHandler* FromAddress(Address address); 95 96 private: 97 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler); 98 }; 99 100 101 #define STACK_FRAME_TYPE_LIST(V) \ 102 V(ENTRY, EntryFrame) \ 103 V(ENTRY_CONSTRUCT, EntryConstructFrame) \ 104 V(EXIT, ExitFrame) \ 105 V(JAVA_SCRIPT, JavaScriptFrame) \ 106 V(OPTIMIZED, OptimizedFrame) \ 107 V(INTERPRETED, InterpretedFrame) \ 108 V(STUB, StubFrame) \ 109 V(STUB_FAILURE_TRAMPOLINE, StubFailureTrampolineFrame) \ 110 V(INTERNAL, InternalFrame) \ 111 V(CONSTRUCT, ConstructFrame) \ 112 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame) 113 114 115 class StandardFrameConstants : public AllStatic { 116 public: 117 // Fixed part of the frame consists of return address, caller fp, 118 // constant pool (if FLAG_enable_embedded_constant_pool), context, and 119 // function. StandardFrame::IterateExpressions assumes that kLastObjectOffset 120 // is the last object pointer. 121 static const int kCPSlotSize = 122 FLAG_enable_embedded_constant_pool ? kPointerSize : 0; 123 static const int kFixedFrameSizeFromFp = 2 * kPointerSize + kCPSlotSize; 124 static const int kFixedFrameSizeAboveFp = kPCOnStackSize + kFPOnStackSize; 125 static const int kFixedFrameSize = 126 kFixedFrameSizeAboveFp + kFixedFrameSizeFromFp; 127 static const int kFixedSlotCountAboveFp = 128 kFixedFrameSizeAboveFp / kPointerSize; 129 static const int kFixedSlotCount = kFixedFrameSize / kPointerSize; 130 static const int kCPSlotCount = kCPSlotSize / kPointerSize; 131 static const int kExpressionsOffset = -3 * kPointerSize - kCPSlotSize; 132 static const int kMarkerOffset = -2 * kPointerSize - kCPSlotSize; 133 static const int kContextOffset = -1 * kPointerSize - kCPSlotSize; 134 static const int kConstantPoolOffset = kCPSlotSize ? -1 * kPointerSize : 0; 135 static const int kCallerFPOffset = 0 * kPointerSize; 136 static const int kCallerPCOffset = +1 * kFPOnStackSize; 137 static const int kCallerSPOffset = kCallerPCOffset + 1 * kPCOnStackSize; 138 139 static const int kLastObjectOffset = kContextOffset; 140 }; 141 142 143 class ArgumentsAdaptorFrameConstants : public AllStatic { 144 public: 145 // FP-relative. 146 static const int kLengthOffset = StandardFrameConstants::kExpressionsOffset; 147 148 static const int kFrameSize = 149 StandardFrameConstants::kFixedFrameSize + kPointerSize; 150 }; 151 152 153 class InternalFrameConstants : public AllStatic { 154 public: 155 // FP-relative. 156 static const int kCodeOffset = StandardFrameConstants::kExpressionsOffset; 157 }; 158 159 160 class ConstructFrameConstants : public AllStatic { 161 public: 162 // FP-relative. 163 static const int kImplicitReceiverOffset = 164 StandardFrameConstants::kExpressionsOffset - 3 * kPointerSize; 165 static const int kLengthOffset = 166 StandardFrameConstants::kExpressionsOffset - 2 * kPointerSize; 167 static const int kAllocationSiteOffset = 168 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 169 static const int kCodeOffset = 170 StandardFrameConstants::kExpressionsOffset - 0 * kPointerSize; 171 172 static const int kFrameSize = 173 StandardFrameConstants::kFixedFrameSize + 4 * kPointerSize; 174 }; 175 176 177 class InterpreterFrameConstants : public AllStatic { 178 public: 179 // Fixed frame includes new.target and bytecode offset. 180 static const int kFixedFrameSize = 181 StandardFrameConstants::kFixedFrameSize + 2 * kPointerSize; 182 static const int kFixedFrameSizeFromFp = 183 StandardFrameConstants::kFixedFrameSizeFromFp + 2 * kPointerSize; 184 185 // FP-relative. 186 static const int kRegisterFilePointerFromFp = 187 -StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kPointerSize; 188 189 // Register file pointer relative. 190 static const int kLastParamFromRegisterPointer = 191 StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize; 192 193 static const int kBytecodeOffsetFromRegisterPointer = 1 * kPointerSize; 194 static const int kNewTargetFromRegisterPointer = 2 * kPointerSize; 195 static const int kFunctionFromRegisterPointer = 3 * kPointerSize; 196 static const int kContextFromRegisterPointer = 4 * kPointerSize; 197 }; 198 199 200 // Abstract base class for all stack frames. 201 class StackFrame BASE_EMBEDDED { 202 public: 203 #define DECLARE_TYPE(type, ignore) type, 204 enum Type { 205 NONE = 0, 206 STACK_FRAME_TYPE_LIST(DECLARE_TYPE) 207 NUMBER_OF_TYPES, 208 // Used by FrameScope to indicate that the stack frame is constructed 209 // manually and the FrameScope does not need to emit code. 210 MANUAL 211 }; 212 #undef DECLARE_TYPE 213 214 // Opaque data type for identifying stack frames. Used extensively 215 // by the debugger. 216 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type 217 // has correct value range (see Issue 830 for more details). 218 enum Id { 219 ID_MIN_VALUE = kMinInt, 220 ID_MAX_VALUE = kMaxInt, 221 NO_ID = 0 222 }; 223 224 // Used to mark the outermost JS entry frame. 225 enum JsFrameMarker { 226 INNER_JSENTRY_FRAME = 0, 227 OUTERMOST_JSENTRY_FRAME = 1 228 }; 229 230 struct State { StateState231 State() : sp(NULL), fp(NULL), pc_address(NULL), 232 constant_pool_address(NULL) { } 233 Address sp; 234 Address fp; 235 Address* pc_address; 236 Address* constant_pool_address; 237 }; 238 239 // Copy constructor; it breaks the connection to host iterator 240 // (as an iterator usually lives on stack). StackFrame(const StackFrame & original)241 StackFrame(const StackFrame& original) { 242 this->state_ = original.state_; 243 this->iterator_ = NULL; 244 this->isolate_ = original.isolate_; 245 } 246 247 // Type testers. is_entry()248 bool is_entry() const { return type() == ENTRY; } is_entry_construct()249 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; } is_exit()250 bool is_exit() const { return type() == EXIT; } is_optimized()251 bool is_optimized() const { return type() == OPTIMIZED; } is_arguments_adaptor()252 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; } is_internal()253 bool is_internal() const { return type() == INTERNAL; } is_stub_failure_trampoline()254 bool is_stub_failure_trampoline() const { 255 return type() == STUB_FAILURE_TRAMPOLINE; 256 } is_construct()257 bool is_construct() const { return type() == CONSTRUCT; } is_standard()258 virtual bool is_standard() const { return false; } 259 is_java_script()260 bool is_java_script() const { 261 Type type = this->type(); 262 return (type == JAVA_SCRIPT) || (type == OPTIMIZED) || 263 (type == INTERPRETED); 264 } 265 266 // Accessors. sp()267 Address sp() const { return state_.sp; } fp()268 Address fp() const { return state_.fp; } caller_sp()269 Address caller_sp() const { return GetCallerStackPointer(); } 270 271 // If this frame is optimized and was dynamically aligned return its old 272 // unaligned frame pointer. When the frame is deoptimized its FP will shift 273 // up one word and become unaligned. 274 Address UnpaddedFP() const; 275 pc()276 Address pc() const { return *pc_address(); } set_pc(Address pc)277 void set_pc(Address pc) { *pc_address() = pc; } 278 constant_pool()279 Address constant_pool() const { return *constant_pool_address(); } set_constant_pool(Address constant_pool)280 void set_constant_pool(Address constant_pool) { 281 *constant_pool_address() = constant_pool; 282 } 283 284 virtual void SetCallerFp(Address caller_fp) = 0; 285 286 // Manually changes value of fp in this object. UpdateFp(Address fp)287 void UpdateFp(Address fp) { state_.fp = fp; } 288 pc_address()289 Address* pc_address() const { return state_.pc_address; } 290 constant_pool_address()291 Address* constant_pool_address() const { 292 return state_.constant_pool_address; 293 } 294 295 // Get the id of this stack frame. id()296 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); } 297 298 // Get the top handler from the current stack iterator. 299 inline StackHandler* top_handler() const; 300 301 // Get the type of this frame. 302 virtual Type type() const = 0; 303 304 // Get the code associated with this frame. 305 // This method could be called during marking phase of GC. 306 virtual Code* unchecked_code() const = 0; 307 308 // Get the code associated with this frame. 309 inline Code* LookupCode() const; 310 311 // Get the code object that contains the given pc. 312 static inline Code* GetContainingCode(Isolate* isolate, Address pc); 313 314 // Get the code object containing the given pc and fill in the 315 // safepoint entry and the number of stack slots. The pc must be at 316 // a safepoint. 317 static Code* GetSafepointData(Isolate* isolate, 318 Address pc, 319 SafepointEntry* safepoint_entry, 320 unsigned* stack_slots); 321 322 virtual void Iterate(ObjectVisitor* v) const = 0; 323 static void IteratePc(ObjectVisitor* v, Address* pc_address, 324 Address* constant_pool_address, Code* holder); 325 326 // Sets a callback function for return-address rewriting profilers 327 // to resolve the location of a return address to the location of the 328 // profiler's stashed return address. 329 static void SetReturnAddressLocationResolver( 330 ReturnAddressLocationResolver resolver); 331 332 // Resolves pc_address through the resolution address function if one is set. 333 static inline Address* ResolveReturnAddressLocation(Address* pc_address); 334 335 // Printing support. 336 enum PrintMode { OVERVIEW, DETAILS }; Print(StringStream * accumulator,PrintMode mode,int index)337 virtual void Print(StringStream* accumulator, 338 PrintMode mode, 339 int index) const { } 340 isolate()341 Isolate* isolate() const { return isolate_; } 342 343 protected: 344 inline explicit StackFrame(StackFrameIteratorBase* iterator); ~StackFrame()345 virtual ~StackFrame() { } 346 347 // Compute the stack pointer for the calling frame. 348 virtual Address GetCallerStackPointer() const = 0; 349 350 // Printing support. 351 static void PrintIndex(StringStream* accumulator, 352 PrintMode mode, 353 int index); 354 355 // Compute the stack frame type for the given state. 356 static Type ComputeType(const StackFrameIteratorBase* iterator, State* state); 357 358 #ifdef DEBUG 359 bool can_access_heap_objects() const; 360 #endif 361 362 private: 363 const StackFrameIteratorBase* iterator_; 364 Isolate* isolate_; 365 State state_; 366 367 static ReturnAddressLocationResolver return_address_location_resolver_; 368 369 // Fill in the state of the calling frame. 370 virtual void ComputeCallerState(State* state) const = 0; 371 372 // Get the type and the state of the calling frame. 373 virtual Type GetCallerState(State* state) const; 374 375 static const intptr_t kIsolateTag = 1; 376 377 friend class StackFrameIterator; 378 friend class StackFrameIteratorBase; 379 friend class StackHandlerIterator; 380 friend class SafeStackFrameIterator; 381 382 private: 383 void operator=(const StackFrame& original); 384 }; 385 386 387 // Entry frames are used to enter JavaScript execution from C. 388 class EntryFrame: public StackFrame { 389 public: type()390 Type type() const override { return ENTRY; } 391 392 Code* unchecked_code() const override; 393 394 // Garbage collection support. 395 void Iterate(ObjectVisitor* v) const override; 396 cast(StackFrame * frame)397 static EntryFrame* cast(StackFrame* frame) { 398 DCHECK(frame->is_entry()); 399 return static_cast<EntryFrame*>(frame); 400 } 401 void SetCallerFp(Address caller_fp) override; 402 403 protected: 404 inline explicit EntryFrame(StackFrameIteratorBase* iterator); 405 406 // The caller stack pointer for entry frames is always zero. The 407 // real information about the caller frame is available through the 408 // link to the top exit frame. GetCallerStackPointer()409 Address GetCallerStackPointer() const override { return 0; } 410 411 private: 412 void ComputeCallerState(State* state) const override; 413 Type GetCallerState(State* state) const override; 414 415 friend class StackFrameIteratorBase; 416 }; 417 418 419 class EntryConstructFrame: public EntryFrame { 420 public: type()421 Type type() const override { return ENTRY_CONSTRUCT; } 422 423 Code* unchecked_code() const override; 424 cast(StackFrame * frame)425 static EntryConstructFrame* cast(StackFrame* frame) { 426 DCHECK(frame->is_entry_construct()); 427 return static_cast<EntryConstructFrame*>(frame); 428 } 429 430 protected: 431 inline explicit EntryConstructFrame(StackFrameIteratorBase* iterator); 432 433 private: 434 friend class StackFrameIteratorBase; 435 }; 436 437 438 // Exit frames are used to exit JavaScript execution and go to C. 439 class ExitFrame: public StackFrame { 440 public: type()441 Type type() const override { return EXIT; } 442 443 Code* unchecked_code() const override; 444 445 Object*& code_slot() const; 446 447 // Garbage collection support. 448 void Iterate(ObjectVisitor* v) const override; 449 450 void SetCallerFp(Address caller_fp) override; 451 cast(StackFrame * frame)452 static ExitFrame* cast(StackFrame* frame) { 453 DCHECK(frame->is_exit()); 454 return static_cast<ExitFrame*>(frame); 455 } 456 457 // Compute the state and type of an exit frame given a frame 458 // pointer. Used when constructing the first stack frame seen by an 459 // iterator and the frames following entry frames. 460 static Type GetStateForFramePointer(Address fp, State* state); 461 static Address ComputeStackPointer(Address fp); 462 static void FillState(Address fp, Address sp, State* state); 463 464 protected: 465 inline explicit ExitFrame(StackFrameIteratorBase* iterator); 466 467 Address GetCallerStackPointer() const override; 468 469 private: 470 void ComputeCallerState(State* state) const override; 471 472 friend class StackFrameIteratorBase; 473 }; 474 475 476 class StandardFrame: public StackFrame { 477 public: 478 // Testers. is_standard()479 bool is_standard() const override { return true; } 480 481 // Accessors. 482 inline Object* context() const; 483 484 // Access the expressions in the stack frame including locals. 485 inline Object* GetExpression(int index) const; 486 inline void SetExpression(int index, Object* value); 487 int ComputeExpressionsCount() const; 488 static Object* GetExpression(Address fp, int index); 489 490 void SetCallerFp(Address caller_fp) override; 491 cast(StackFrame * frame)492 static StandardFrame* cast(StackFrame* frame) { 493 DCHECK(frame->is_standard()); 494 return static_cast<StandardFrame*>(frame); 495 } 496 497 protected: 498 inline explicit StandardFrame(StackFrameIteratorBase* iterator); 499 500 void ComputeCallerState(State* state) const override; 501 502 // Accessors. 503 inline Address caller_fp() const; 504 inline Address caller_pc() const; 505 506 // Computes the address of the PC field in the standard frame given 507 // by the provided frame pointer. 508 static inline Address ComputePCAddress(Address fp); 509 510 // Computes the address of the constant pool field in the standard 511 // frame given by the provided frame pointer. 512 static inline Address ComputeConstantPoolAddress(Address fp); 513 514 // Iterate over expression stack including stack handlers, locals, 515 // and parts of the fixed part including context and code fields. 516 void IterateExpressions(ObjectVisitor* v) const; 517 518 // Returns the address of the n'th expression stack element. 519 Address GetExpressionAddress(int n) const; 520 static Address GetExpressionAddress(Address fp, int n); 521 522 // Determines if the standard frame for the given frame pointer is 523 // an arguments adaptor frame. 524 static inline bool IsArgumentsAdaptorFrame(Address fp); 525 526 // Determines if the standard frame for the given frame pointer is a 527 // construct frame. 528 static inline bool IsConstructFrame(Address fp); 529 530 // Used by OptimizedFrames and StubFrames. 531 void IterateCompiledFrame(ObjectVisitor* v) const; 532 533 private: 534 friend class StackFrame; 535 friend class SafeStackFrameIterator; 536 }; 537 538 539 class FrameSummary BASE_EMBEDDED { 540 public: 541 FrameSummary(Object* receiver, JSFunction* function, Code* code, int offset, 542 bool is_constructor); 543 receiver()544 Handle<Object> receiver() { return receiver_; } function()545 Handle<JSFunction> function() { return function_; } code()546 Handle<Code> code() { return code_; } pc()547 Address pc() { return code_->address() + offset_; } offset()548 int offset() { return offset_; } is_constructor()549 bool is_constructor() { return is_constructor_; } 550 551 void Print(); 552 553 private: 554 Handle<Object> receiver_; 555 Handle<JSFunction> function_; 556 Handle<Code> code_; 557 int offset_; 558 bool is_constructor_; 559 }; 560 561 562 class JavaScriptFrame: public StandardFrame { 563 public: type()564 Type type() const override { return JAVA_SCRIPT; } 565 566 // Accessors. 567 inline JSFunction* function() const; 568 inline Object* receiver() const; 569 inline void set_receiver(Object* value); 570 571 // Access the parameters. 572 inline Address GetParameterSlot(int index) const; 573 inline Object* GetParameter(int index) const; ComputeParametersCount()574 inline int ComputeParametersCount() const { 575 return GetNumberOfIncomingArguments(); 576 } 577 578 // Access the operand stack. 579 inline Address GetOperandSlot(int index) const; 580 inline Object* GetOperand(int index) const; 581 inline int ComputeOperandsCount() const; 582 583 // Generator support to preserve operand stack. 584 void SaveOperandStack(FixedArray* store) const; 585 void RestoreOperandStack(FixedArray* store); 586 587 // Debugger access. 588 void SetParameterValue(int index, Object* value) const; 589 590 // Check if this frame is a constructor frame invoked through 'new'. 591 bool IsConstructor() const; 592 593 // Determines whether this frame includes inlined activations. To get details 594 // about the inlined frames use {GetFunctions} and {Summarize}. 595 bool HasInlinedFrames() const; 596 597 // Check if this frame has "adapted" arguments in the sense that the 598 // actual passed arguments are available in an arguments adaptor 599 // frame below it on the stack. 600 inline bool has_adapted_arguments() const; 601 int GetArgumentsLength() const; 602 603 // Garbage collection support. 604 void Iterate(ObjectVisitor* v) const override; 605 606 // Printing support. 607 void Print(StringStream* accumulator, PrintMode mode, 608 int index) const override; 609 610 // Determine the code for the frame. 611 Code* unchecked_code() const override; 612 613 // Return a list with JSFunctions of this frame. 614 virtual void GetFunctions(List<JSFunction*>* functions) const; 615 616 // Build a list with summaries for this frame including all inlined frames. 617 virtual void Summarize(List<FrameSummary>* frames); 618 619 // Lookup exception handler for current {pc}, returns -1 if none found. Also 620 // returns the expected number of stack slots at the handler site. 621 virtual int LookupExceptionHandlerInTable( 622 int* stack_slots, HandlerTable::CatchPrediction* prediction); 623 624 // Architecture-specific register description. 625 static Register fp_register(); 626 static Register context_register(); 627 static Register constant_pool_pointer_register(); 628 cast(StackFrame * frame)629 static JavaScriptFrame* cast(StackFrame* frame) { 630 DCHECK(frame->is_java_script()); 631 return static_cast<JavaScriptFrame*>(frame); 632 } 633 634 static void PrintFunctionAndOffset(JSFunction* function, Code* code, 635 Address pc, FILE* file, 636 bool print_line_number); 637 638 static void PrintTop(Isolate* isolate, FILE* file, bool print_args, 639 bool print_line_number); 640 641 protected: 642 inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator); 643 644 Address GetCallerStackPointer() const override; 645 646 virtual int GetNumberOfIncomingArguments() const; 647 648 // Garbage collection support. Iterates over incoming arguments, 649 // receiver, and any callee-saved registers. 650 void IterateArguments(ObjectVisitor* v) const; 651 652 private: 653 inline Object* function_slot_object() const; 654 655 friend class StackFrameIteratorBase; 656 }; 657 658 659 class StubFrame : public StandardFrame { 660 public: type()661 Type type() const override { return STUB; } 662 663 // GC support. 664 void Iterate(ObjectVisitor* v) const override; 665 666 // Determine the code for the frame. 667 Code* unchecked_code() const override; 668 669 protected: 670 inline explicit StubFrame(StackFrameIteratorBase* iterator); 671 672 Address GetCallerStackPointer() const override; 673 674 virtual int GetNumberOfIncomingArguments() const; 675 676 friend class StackFrameIteratorBase; 677 }; 678 679 680 class OptimizedFrame : public JavaScriptFrame { 681 public: type()682 Type type() const override { return OPTIMIZED; } 683 684 // GC support. 685 void Iterate(ObjectVisitor* v) const override; 686 687 // Return a list with JSFunctions of this frame. 688 // The functions are ordered bottom-to-top (i.e. functions.last() 689 // is the top-most activation) 690 void GetFunctions(List<JSFunction*>* functions) const override; 691 692 void Summarize(List<FrameSummary>* frames) override; 693 694 // Lookup exception handler for current {pc}, returns -1 if none found. Also 695 // returns the expected number of stack slots at the handler site. 696 int LookupExceptionHandlerInTable( 697 int* stack_slots, HandlerTable::CatchPrediction* prediction) override; 698 699 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index) const; 700 701 static int StackSlotOffsetRelativeToFp(int slot_index); 702 703 protected: 704 inline explicit OptimizedFrame(StackFrameIteratorBase* iterator); 705 706 private: 707 friend class StackFrameIteratorBase; 708 709 Object* StackSlotAt(int index) const; 710 }; 711 712 713 class InterpretedFrame : public JavaScriptFrame { type()714 Type type() const override { return INTERPRETED; } 715 716 protected: 717 inline explicit InterpretedFrame(StackFrameIteratorBase* iterator); 718 719 private: 720 friend class StackFrameIteratorBase; 721 }; 722 723 724 // Arguments adaptor frames are automatically inserted below 725 // JavaScript frames when the actual number of parameters does not 726 // match the formal number of parameters. 727 class ArgumentsAdaptorFrame: public JavaScriptFrame { 728 public: type()729 Type type() const override { return ARGUMENTS_ADAPTOR; } 730 731 // Determine the code for the frame. 732 Code* unchecked_code() const override; 733 cast(StackFrame * frame)734 static ArgumentsAdaptorFrame* cast(StackFrame* frame) { 735 DCHECK(frame->is_arguments_adaptor()); 736 return static_cast<ArgumentsAdaptorFrame*>(frame); 737 } 738 739 // Printing support. 740 void Print(StringStream* accumulator, PrintMode mode, 741 int index) const override; 742 743 protected: 744 inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator); 745 746 int GetNumberOfIncomingArguments() const override; 747 748 Address GetCallerStackPointer() const override; 749 750 private: 751 friend class StackFrameIteratorBase; 752 }; 753 754 755 class InternalFrame: public StandardFrame { 756 public: type()757 Type type() const override { return INTERNAL; } 758 759 // Garbage collection support. 760 void Iterate(ObjectVisitor* v) const override; 761 762 // Determine the code for the frame. 763 Code* unchecked_code() const override; 764 cast(StackFrame * frame)765 static InternalFrame* cast(StackFrame* frame) { 766 DCHECK(frame->is_internal()); 767 return static_cast<InternalFrame*>(frame); 768 } 769 770 protected: 771 inline explicit InternalFrame(StackFrameIteratorBase* iterator); 772 773 Address GetCallerStackPointer() const override; 774 775 private: 776 friend class StackFrameIteratorBase; 777 }; 778 779 780 class StubFailureTrampolineFrame: public StandardFrame { 781 public: 782 // sizeof(Arguments) - sizeof(Arguments*) is 3 * kPointerSize), but the 783 // presubmit script complains about using sizeof() on a type. 784 static const int kFirstRegisterParameterFrameOffset = 785 StandardFrameConstants::kMarkerOffset - 3 * kPointerSize; 786 787 static const int kCallerStackParameterCountFrameOffset = 788 StandardFrameConstants::kMarkerOffset - 2 * kPointerSize; 789 type()790 Type type() const override { return STUB_FAILURE_TRAMPOLINE; } 791 792 // Get the code associated with this frame. 793 // This method could be called during marking phase of GC. 794 Code* unchecked_code() const override; 795 796 void Iterate(ObjectVisitor* v) const override; 797 798 // Architecture-specific register description. 799 static Register fp_register(); 800 static Register context_register(); 801 static Register constant_pool_pointer_register(); 802 803 protected: 804 inline explicit StubFailureTrampolineFrame( 805 StackFrameIteratorBase* iterator); 806 807 Address GetCallerStackPointer() const override; 808 809 private: 810 friend class StackFrameIteratorBase; 811 }; 812 813 814 // Construct frames are special trampoline frames introduced to handle 815 // function invocations through 'new'. 816 class ConstructFrame: public InternalFrame { 817 public: type()818 Type type() const override { return CONSTRUCT; } 819 cast(StackFrame * frame)820 static ConstructFrame* cast(StackFrame* frame) { 821 DCHECK(frame->is_construct()); 822 return static_cast<ConstructFrame*>(frame); 823 } 824 825 protected: 826 inline explicit ConstructFrame(StackFrameIteratorBase* iterator); 827 828 private: 829 friend class StackFrameIteratorBase; 830 }; 831 832 833 class StackFrameIteratorBase BASE_EMBEDDED { 834 public: isolate()835 Isolate* isolate() const { return isolate_; } 836 done()837 bool done() const { return frame_ == NULL; } 838 839 protected: 840 // An iterator that iterates over a given thread's stack. 841 StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects); 842 843 Isolate* isolate_; 844 #define DECLARE_SINGLETON(ignore, type) type type##_; 845 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON) 846 #undef DECLARE_SINGLETON 847 StackFrame* frame_; 848 StackHandler* handler_; 849 const bool can_access_heap_objects_; 850 handler()851 StackHandler* handler() const { 852 DCHECK(!done()); 853 return handler_; 854 } 855 856 // Get the type-specific frame singleton in a given state. 857 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state); 858 // A helper function, can return a NULL pointer. 859 StackFrame* SingletonFor(StackFrame::Type type); 860 861 private: 862 friend class StackFrame; 863 DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase); 864 }; 865 866 867 class StackFrameIterator: public StackFrameIteratorBase { 868 public: 869 // An iterator that iterates over the isolate's current thread's stack, 870 explicit StackFrameIterator(Isolate* isolate); 871 // An iterator that iterates over a given thread's stack. 872 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t); 873 frame()874 StackFrame* frame() const { 875 DCHECK(!done()); 876 return frame_; 877 } 878 void Advance(); 879 880 private: 881 // Go back to the first frame. 882 void Reset(ThreadLocalTop* top); 883 884 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); 885 }; 886 887 888 // Iterator that supports iterating through all JavaScript frames. 889 class JavaScriptFrameIterator BASE_EMBEDDED { 890 public: 891 inline explicit JavaScriptFrameIterator(Isolate* isolate); 892 inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top); 893 // Skip frames until the frame with the given id is reached. 894 JavaScriptFrameIterator(Isolate* isolate, StackFrame::Id id); 895 896 inline JavaScriptFrame* frame() const; 897 done()898 bool done() const { return iterator_.done(); } 899 void Advance(); 900 901 // Advance to the frame holding the arguments for the current 902 // frame. This only affects the current frame if it has adapted 903 // arguments. 904 void AdvanceToArgumentsFrame(); 905 906 private: 907 StackFrameIterator iterator_; 908 }; 909 910 911 // NOTE: The stack trace frame iterator is an iterator that only 912 // traverse proper JavaScript frames; that is JavaScript frames that 913 // have proper JavaScript functions. This excludes the problematic 914 // functions in runtime.js. 915 class StackTraceFrameIterator: public JavaScriptFrameIterator { 916 public: 917 explicit StackTraceFrameIterator(Isolate* isolate); 918 void Advance(); 919 920 private: 921 bool IsValidFrame(); 922 }; 923 924 925 class SafeStackFrameIterator: public StackFrameIteratorBase { 926 public: 927 SafeStackFrameIterator(Isolate* isolate, 928 Address fp, Address sp, 929 Address js_entry_sp); 930 931 inline StackFrame* frame() const; 932 void Advance(); 933 top_frame_type()934 StackFrame::Type top_frame_type() const { return top_frame_type_; } 935 936 private: 937 void AdvanceOneFrame(); 938 IsValidStackAddress(Address addr)939 bool IsValidStackAddress(Address addr) const { 940 return low_bound_ <= addr && addr <= high_bound_; 941 } 942 bool IsValidFrame(StackFrame* frame) const; 943 bool IsValidCaller(StackFrame* frame); 944 bool IsValidExitFrame(Address fp) const; 945 bool IsValidTop(ThreadLocalTop* top) const; 946 947 const Address low_bound_; 948 const Address high_bound_; 949 StackFrame::Type top_frame_type_; 950 ExternalCallbackScope* external_callback_scope_; 951 }; 952 953 954 class StackFrameLocator BASE_EMBEDDED { 955 public: StackFrameLocator(Isolate * isolate)956 explicit StackFrameLocator(Isolate* isolate) : iterator_(isolate) {} 957 958 // Find the nth JavaScript frame on the stack. The caller must 959 // guarantee that such a frame exists. 960 JavaScriptFrame* FindJavaScriptFrame(int n); 961 962 private: 963 StackFrameIterator iterator_; 964 }; 965 966 967 // Reads all frames on the current stack and copies them into the current 968 // zone memory. 969 Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone); 970 971 } // namespace internal 972 } // namespace v8 973 974 #endif // V8_FRAMES_H_ 975