| OLD | NEW |
| 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 // Get the top handler from the current stack iterator. | 183 // Get the top handler from the current stack iterator. |
| 184 inline StackHandler* top_handler() const; | 184 inline StackHandler* top_handler() const; |
| 185 | 185 |
| 186 // Compute the stack frame type for the given state. | 186 // Compute the stack frame type for the given state. |
| 187 static Type ComputeType(State* state); | 187 static Type ComputeType(State* state); |
| 188 | 188 |
| 189 private: | 189 private: |
| 190 const StackFrameIterator* iterator_; | 190 const StackFrameIterator* iterator_; |
| 191 State state_; | 191 State state_; |
| 192 | 192 |
| 193 // Fill in the state of the calling frame. |
| 194 virtual void ComputeCallerState(State* state) const = 0; |
| 195 |
| 193 // Get the type and the state of the calling frame. | 196 // Get the type and the state of the calling frame. |
| 194 virtual Type GetCallerState(State* state) const = 0; | 197 virtual Type GetCallerState(State* state) const; |
| 195 | 198 |
| 196 // Cooking/uncooking support. | 199 // Cooking/uncooking support. |
| 197 void Cook(); | 200 void Cook(); |
| 198 void Uncook(); | 201 void Uncook(); |
| 199 | 202 |
| 200 friend class StackFrameIterator; | 203 friend class StackFrameIterator; |
| 201 friend class StackHandlerIterator; | 204 friend class StackHandlerIterator; |
| 205 friend class SafeStackFrameIterator; |
| 202 | 206 |
| 203 DISALLOW_IMPLICIT_CONSTRUCTORS(StackFrame); | 207 DISALLOW_IMPLICIT_CONSTRUCTORS(StackFrame); |
| 204 }; | 208 }; |
| 205 | 209 |
| 206 | 210 |
| 207 // Entry frames are used to enter JavaScript execution from C. | 211 // Entry frames are used to enter JavaScript execution from C. |
| 208 class EntryFrame: public StackFrame { | 212 class EntryFrame: public StackFrame { |
| 209 public: | 213 public: |
| 210 virtual Type type() const { return ENTRY; } | 214 virtual Type type() const { return ENTRY; } |
| 211 | 215 |
| 212 virtual Code* code() const; | 216 virtual Code* code() const; |
| 213 | 217 |
| 214 // Garbage collection support. | 218 // Garbage collection support. |
| 215 virtual void Iterate(ObjectVisitor* v) const; | 219 virtual void Iterate(ObjectVisitor* v) const; |
| 216 | 220 |
| 217 static EntryFrame* cast(StackFrame* frame) { | 221 static EntryFrame* cast(StackFrame* frame) { |
| 218 ASSERT(frame->is_entry()); | 222 ASSERT(frame->is_entry()); |
| 219 return static_cast<EntryFrame*>(frame); | 223 return static_cast<EntryFrame*>(frame); |
| 220 } | 224 } |
| 221 | 225 |
| 222 protected: | 226 protected: |
| 223 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { } | 227 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { } |
| 224 | 228 |
| 225 // The caller stack pointer for entry frames is always zero. The | 229 // The caller stack pointer for entry frames is always zero. The |
| 226 // real information about the caller frame is available through the | 230 // real information about the caller frame is available through the |
| 227 // link to the top exit frame. | 231 // link to the top exit frame. |
| 228 virtual Address GetCallerStackPointer() const { return 0; } | 232 virtual Address GetCallerStackPointer() const { return 0; } |
| 229 | 233 |
| 230 private: | 234 private: |
| 235 virtual void ComputeCallerState(State* state) const; |
| 231 virtual Type GetCallerState(State* state) const; | 236 virtual Type GetCallerState(State* state) const; |
| 232 | 237 |
| 233 friend class StackFrameIterator; | 238 friend class StackFrameIterator; |
| 234 }; | 239 }; |
| 235 | 240 |
| 236 | 241 |
| 237 class EntryConstructFrame: public EntryFrame { | 242 class EntryConstructFrame: public EntryFrame { |
| 238 public: | 243 public: |
| 239 virtual Type type() const { return ENTRY_CONSTRUCT; } | 244 virtual Type type() const { return ENTRY_CONSTRUCT; } |
| 240 | 245 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 // pointer. Used when constructing the first stack frame seen by an | 278 // pointer. Used when constructing the first stack frame seen by an |
| 274 // iterator and the frames following entry frames. | 279 // iterator and the frames following entry frames. |
| 275 static Type GetStateForFramePointer(Address fp, State* state); | 280 static Type GetStateForFramePointer(Address fp, State* state); |
| 276 | 281 |
| 277 protected: | 282 protected: |
| 278 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { } | 283 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { } |
| 279 | 284 |
| 280 virtual Address GetCallerStackPointer() const; | 285 virtual Address GetCallerStackPointer() const; |
| 281 | 286 |
| 282 private: | 287 private: |
| 283 virtual Type GetCallerState(State* state) const; | 288 virtual void ComputeCallerState(State* state) const; |
| 284 | 289 |
| 285 friend class StackFrameIterator; | 290 friend class StackFrameIterator; |
| 286 }; | 291 }; |
| 287 | 292 |
| 288 | 293 |
| 289 class ExitDebugFrame: public ExitFrame { | 294 class ExitDebugFrame: public ExitFrame { |
| 290 public: | 295 public: |
| 291 virtual Type type() const { return EXIT_DEBUG; } | 296 virtual Type type() const { return EXIT_DEBUG; } |
| 292 | 297 |
| 293 virtual Code* code() const; | 298 virtual Code* code() const; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 321 | 326 |
| 322 static StandardFrame* cast(StackFrame* frame) { | 327 static StandardFrame* cast(StackFrame* frame) { |
| 323 ASSERT(frame->is_standard()); | 328 ASSERT(frame->is_standard()); |
| 324 return static_cast<StandardFrame*>(frame); | 329 return static_cast<StandardFrame*>(frame); |
| 325 } | 330 } |
| 326 | 331 |
| 327 protected: | 332 protected: |
| 328 explicit StandardFrame(StackFrameIterator* iterator) | 333 explicit StandardFrame(StackFrameIterator* iterator) |
| 329 : StackFrame(iterator) { } | 334 : StackFrame(iterator) { } |
| 330 | 335 |
| 331 virtual Type GetCallerState(State* state) const; | 336 virtual void ComputeCallerState(State* state) const; |
| 332 | 337 |
| 333 // Accessors. | 338 // Accessors. |
| 334 inline Address caller_sp() const; | 339 inline Address caller_sp() const; |
| 335 inline Address caller_fp() const; | 340 inline Address caller_fp() const; |
| 336 inline Address caller_pc() const; | 341 inline Address caller_pc() const; |
| 337 | 342 |
| 338 // Computes the address of the PC field in the standard frame given | 343 // Computes the address of the PC field in the standard frame given |
| 339 // by the provided frame pointer. | 344 // by the provided frame pointer. |
| 340 static inline Address ComputePCAddress(Address fp); | 345 static inline Address ComputePCAddress(Address fp); |
| 341 | 346 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 361 private: | 366 private: |
| 362 friend class StackFrame; | 367 friend class StackFrame; |
| 363 }; | 368 }; |
| 364 | 369 |
| 365 | 370 |
| 366 class JavaScriptFrame: public StandardFrame { | 371 class JavaScriptFrame: public StandardFrame { |
| 367 public: | 372 public: |
| 368 virtual Type type() const { return JAVA_SCRIPT; } | 373 virtual Type type() const { return JAVA_SCRIPT; } |
| 369 | 374 |
| 370 // Accessors. | 375 // Accessors. |
| 376 inline bool is_at_function() const; |
| 371 inline Object* function() const; | 377 inline Object* function() const; |
| 372 inline Object* receiver() const; | 378 inline Object* receiver() const; |
| 373 inline void set_receiver(Object* value); | 379 inline void set_receiver(Object* value); |
| 374 | 380 |
| 375 // Access the parameters. | 381 // Access the parameters. |
| 376 Object* GetParameter(int index) const; | 382 Object* GetParameter(int index) const; |
| 377 int ComputeParametersCount() const; | 383 int ComputeParametersCount() const; |
| 378 | 384 |
| 379 // Temporary way of getting access to the number of parameters | 385 // Temporary way of getting access to the number of parameters |
| 380 // passed on the stack by the caller. Once argument adaptor frames | 386 // passed on the stack by the caller. Once argument adaptor frames |
| (...skipping 25 matching lines...) Expand all Loading... |
| 406 return static_cast<JavaScriptFrame*>(frame); | 412 return static_cast<JavaScriptFrame*>(frame); |
| 407 } | 413 } |
| 408 | 414 |
| 409 protected: | 415 protected: |
| 410 explicit JavaScriptFrame(StackFrameIterator* iterator) | 416 explicit JavaScriptFrame(StackFrameIterator* iterator) |
| 411 : StandardFrame(iterator) { } | 417 : StandardFrame(iterator) { } |
| 412 | 418 |
| 413 virtual Address GetCallerStackPointer() const; | 419 virtual Address GetCallerStackPointer() const; |
| 414 | 420 |
| 415 private: | 421 private: |
| 422 inline Object* function_slot_object() const; |
| 423 |
| 416 friend class StackFrameIterator; | 424 friend class StackFrameIterator; |
| 417 }; | 425 }; |
| 418 | 426 |
| 419 | 427 |
| 420 // Arguments adaptor frames are automatically inserted below | 428 // Arguments adaptor frames are automatically inserted below |
| 421 // JavaScript frames when the actual number of parameters does not | 429 // JavaScript frames when the actual number of parameters does not |
| 422 // match the formal number of parameters. | 430 // match the formal number of parameters. |
| 423 class ArgumentsAdaptorFrame: public JavaScriptFrame { | 431 class ArgumentsAdaptorFrame: public JavaScriptFrame { |
| 424 public: | 432 public: |
| 425 // This sentinel value is temporarily used to distinguish arguments | 433 // This sentinel value is temporarily used to distinguish arguments |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 | 510 |
| 503 | 511 |
| 504 class StackFrameIterator BASE_EMBEDDED { | 512 class StackFrameIterator BASE_EMBEDDED { |
| 505 public: | 513 public: |
| 506 // An iterator that iterates over the current thread's stack. | 514 // An iterator that iterates over the current thread's stack. |
| 507 StackFrameIterator(); | 515 StackFrameIterator(); |
| 508 | 516 |
| 509 // An iterator that iterates over a given thread's stack. | 517 // An iterator that iterates over a given thread's stack. |
| 510 explicit StackFrameIterator(ThreadLocalTop* thread); | 518 explicit StackFrameIterator(ThreadLocalTop* thread); |
| 511 | 519 |
| 512 // An iterator that conditionally resets itself on init. | 520 // An iterator that can start from a given FP address. |
| 513 explicit StackFrameIterator(bool reset); | 521 // If use_top, then work as usual, if fp isn't NULL, use it, |
| 522 // otherwise, do nothing. |
| 523 StackFrameIterator(bool use_top, Address fp, Address sp); |
| 514 | 524 |
| 515 StackFrame* frame() const { | 525 StackFrame* frame() const { |
| 516 ASSERT(!done()); | 526 ASSERT(!done()); |
| 517 return frame_; | 527 return frame_; |
| 518 } | 528 } |
| 519 | 529 |
| 520 bool done() const { return frame_ == NULL; } | 530 bool done() const { return frame_ == NULL; } |
| 521 void Advance(); | 531 void Advance() { (this->*advance_)(); } |
| 522 | 532 |
| 523 // Go back to the first frame. | 533 // Go back to the first frame. |
| 524 void Reset(); | 534 void Reset(); |
| 525 | 535 |
| 526 private: | 536 private: |
| 527 #define DECLARE_SINGLETON(ignore, type) type type##_; | 537 #define DECLARE_SINGLETON(ignore, type) type type##_; |
| 528 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON) | 538 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON) |
| 529 #undef DECLARE_SINGLETON | 539 #undef DECLARE_SINGLETON |
| 530 StackFrame* frame_; | 540 StackFrame* frame_; |
| 531 StackHandler* handler_; | 541 StackHandler* handler_; |
| 532 ThreadLocalTop* thread_; | 542 ThreadLocalTop* thread_; |
| 543 Address fp_; |
| 544 Address sp_; |
| 545 void (StackFrameIterator::*advance_)(); |
| 533 | 546 |
| 534 StackHandler* handler() const { | 547 StackHandler* handler() const { |
| 535 ASSERT(!done()); | 548 ASSERT(!done()); |
| 536 return handler_; | 549 return handler_; |
| 537 } | 550 } |
| 538 | 551 |
| 539 // Get the type-specific frame singleton in a given state. | 552 // Get the type-specific frame singleton in a given state. |
| 540 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state); | 553 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state); |
| 554 // A helper function, can return a NULL pointer. |
| 555 StackFrame* SingletonFor(StackFrame::Type type); |
| 556 |
| 557 void AdvanceWithHandler(); |
| 558 void AdvanceWithoutHandler(); |
| 541 | 559 |
| 542 friend class StackFrame; | 560 friend class StackFrame; |
| 561 friend class SafeStackFrameIterator; |
| 543 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); | 562 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator); |
| 544 }; | 563 }; |
| 545 | 564 |
| 546 | 565 |
| 547 // Iterator that supports iterating through all JavaScript frames. | 566 // Iterator that supports iterating through all JavaScript frames. |
| 548 template<typename Iterator> | 567 template<typename Iterator> |
| 549 class JavaScriptFrameIteratorTemp BASE_EMBEDDED { | 568 class JavaScriptFrameIteratorTemp BASE_EMBEDDED { |
| 550 public: | 569 public: |
| 551 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); } | 570 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); } |
| 552 | 571 |
| 553 explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) : | 572 explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) : |
| 554 iterator_(thread) { | 573 iterator_(thread) { |
| 555 if (!done()) Advance(); | 574 if (!done()) Advance(); |
| 556 } | 575 } |
| 557 | 576 |
| 558 // Skip frames until the frame with the given id is reached. | 577 // Skip frames until the frame with the given id is reached. |
| 559 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id); | 578 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id); |
| 560 | 579 |
| 561 explicit JavaScriptFrameIteratorTemp(Address low_bound, Address high_bound) : | 580 JavaScriptFrameIteratorTemp(Address fp, Address sp, |
| 562 iterator_(low_bound, high_bound) { if (!done()) Advance(); } | 581 Address low_bound, Address high_bound) : |
| 582 iterator_(fp, sp, low_bound, high_bound) { |
| 583 if (!done()) Advance(); |
| 584 } |
| 563 | 585 |
| 564 inline JavaScriptFrame* frame() const; | 586 inline JavaScriptFrame* frame() const; |
| 565 | 587 |
| 566 bool done() const { return iterator_.done(); } | 588 bool done() const { return iterator_.done(); } |
| 567 void Advance(); | 589 void Advance(); |
| 568 | 590 |
| 569 // Advance to the frame holding the arguments for the current | 591 // Advance to the frame holding the arguments for the current |
| 570 // frame. This only affects the current frame if it has adapted | 592 // frame. This only affects the current frame if it has adapted |
| 571 // arguments. | 593 // arguments. |
| 572 void AdvanceToArgumentsFrame(); | 594 void AdvanceToArgumentsFrame(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 588 // functions in runtime.js. | 610 // functions in runtime.js. |
| 589 class StackTraceFrameIterator: public JavaScriptFrameIterator { | 611 class StackTraceFrameIterator: public JavaScriptFrameIterator { |
| 590 public: | 612 public: |
| 591 StackTraceFrameIterator(); | 613 StackTraceFrameIterator(); |
| 592 void Advance(); | 614 void Advance(); |
| 593 }; | 615 }; |
| 594 | 616 |
| 595 | 617 |
| 596 class SafeStackFrameIterator BASE_EMBEDDED { | 618 class SafeStackFrameIterator BASE_EMBEDDED { |
| 597 public: | 619 public: |
| 598 explicit SafeStackFrameIterator(Address low_bound, Address high_bound); | 620 SafeStackFrameIterator(Address fp, Address sp, |
| 621 Address low_bound, Address high_bound); |
| 599 | 622 |
| 600 StackFrame* frame() const { | 623 StackFrame* frame() const { |
| 601 ASSERT(is_working_iterator_); | 624 ASSERT(is_working_iterator_); |
| 602 return iterator_.frame(); | 625 return iterator_.frame(); |
| 603 } | 626 } |
| 604 | 627 |
| 605 bool done() const { return iteration_done_ ? true : iterator_.done(); } | 628 bool done() const { return iteration_done_ ? true : iterator_.done(); } |
| 606 | 629 |
| 607 void Advance(); | 630 void Advance(); |
| 608 void Reset(); | 631 void Reset(); |
| 609 | 632 |
| 610 private: | 633 private: |
| 611 static bool IsInBounds( | 634 static bool IsWithinBounds( |
| 612 Address low_bound, Address high_bound, Address addr) { | 635 Address low_bound, Address high_bound, Address addr) { |
| 613 return low_bound <= addr && addr <= high_bound; | 636 return low_bound <= addr && addr <= high_bound; |
| 614 } | 637 } |
| 615 bool IsGoodStackAddress(Address addr) const { | 638 bool IsValidStackAddress(Address addr) const { |
| 616 return IsInBounds(low_bound_, high_bound_, addr); | 639 return IsWithinBounds(low_bound_, high_bound_, addr); |
| 617 } | 640 } |
| 641 bool IsValidFrame(StackFrame* frame) const; |
| 642 bool IsValidCaller(StackFrame* frame); |
| 618 | 643 |
| 619 Address low_bound_; | 644 Address low_bound_; |
| 620 Address high_bound_; | 645 Address high_bound_; |
| 646 const bool is_valid_top_; |
| 647 const bool is_valid_fp_; |
| 621 const bool is_working_iterator_; | 648 const bool is_working_iterator_; |
| 622 bool iteration_done_; | 649 bool iteration_done_; |
| 623 StackFrameIterator iterator_; | 650 StackFrameIterator iterator_; |
| 624 }; | 651 }; |
| 625 | 652 |
| 626 | 653 |
| 627 #ifdef ENABLE_LOGGING_AND_PROFILING | 654 #ifdef ENABLE_LOGGING_AND_PROFILING |
| 628 typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator> | 655 typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator> |
| 629 SafeJavaScriptFrameIterator; | 656 SafeJavaScriptFrameIterator; |
| 630 | 657 |
| 631 | 658 |
| 632 class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator { | 659 class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator { |
| 633 public: | 660 public: |
| 634 explicit SafeStackTraceFrameIterator(Address low_bound, Address high_bound); | 661 explicit SafeStackTraceFrameIterator(Address fp, Address sp, |
| 662 Address low_bound, Address high_bound); |
| 635 void Advance(); | 663 void Advance(); |
| 636 }; | 664 }; |
| 637 #endif | 665 #endif |
| 638 | 666 |
| 639 | 667 |
| 640 class StackFrameLocator BASE_EMBEDDED { | 668 class StackFrameLocator BASE_EMBEDDED { |
| 641 public: | 669 public: |
| 642 // Find the nth JavaScript frame on the stack. The caller must | 670 // Find the nth JavaScript frame on the stack. The caller must |
| 643 // guarantee that such a frame exists. | 671 // guarantee that such a frame exists. |
| 644 JavaScriptFrame* FindJavaScriptFrame(int n); | 672 JavaScriptFrame* FindJavaScriptFrame(int n); |
| 645 | 673 |
| 646 private: | 674 private: |
| 647 StackFrameIterator iterator_; | 675 StackFrameIterator iterator_; |
| 648 }; | 676 }; |
| 649 | 677 |
| 650 | 678 |
| 651 } } // namespace v8::internal | 679 } } // namespace v8::internal |
| 652 | 680 |
| 653 #endif // V8_FRAMES_H_ | 681 #endif // V8_FRAMES_H_ |
| OLD | NEW |