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 |