blob: 2d4f338ae0f7f76f16cfe25fc0c53a8934222619 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_FRAMES_H_
29#define V8_FRAMES_H_
30
31namespace v8 {
32namespace internal {
33
34typedef uint32_t RegList;
35
36// Get the number of registers in a given register list.
37int NumRegs(RegList list);
38
39// Return the code of the n-th saved register available to JavaScript.
40int JSCallerSavedCode(int n);
41
42
43// Forward declarations.
44class StackFrameIterator;
45class Top;
46class ThreadLocalTop;
47
48
Kristian Monsen80d68ea2010-09-08 11:05:35 +010049class PcToCodeCache : AllStatic {
50 public:
51 struct PcToCodeCacheEntry {
52 Address pc;
53 Code* code;
54 };
55
56 static PcToCodeCacheEntry* cache(int index) {
57 return &cache_[index];
58 }
59
60 static Code* GcSafeFindCodeForPc(Address pc);
61 static Code* GcSafeCastToCode(HeapObject* object, Address pc);
62
63 static void FlushPcToCodeCache() {
64 memset(&cache_[0], 0, sizeof(cache_));
65 }
66
67 static PcToCodeCacheEntry* GetCacheEntry(Address pc);
68
69 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +010070 static const int kPcToCodeCacheSize = 1024;
Kristian Monsen80d68ea2010-09-08 11:05:35 +010071 static PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
72};
73
74
Steve Blocka7e24c12009-10-30 11:49:00 +000075class StackHandler BASE_EMBEDDED {
76 public:
77 enum State {
78 ENTRY,
79 TRY_CATCH,
80 TRY_FINALLY
81 };
82
83 // Get the address of this stack handler.
84 inline Address address() const;
85
86 // Get the next stack handler in the chain.
87 inline StackHandler* next() const;
88
89 // Tells whether the given address is inside this handler.
90 inline bool includes(Address address) const;
91
92 // Garbage collection support.
Kristian Monsen80d68ea2010-09-08 11:05:35 +010093 inline void Iterate(ObjectVisitor* v, Code* holder) const;
Steve Blocka7e24c12009-10-30 11:49:00 +000094
95 // Conversion support.
96 static inline StackHandler* FromAddress(Address address);
97
98 // Testers
99 bool is_entry() { return state() == ENTRY; }
100 bool is_try_catch() { return state() == TRY_CATCH; }
101 bool is_try_finally() { return state() == TRY_FINALLY; }
102
Steve Blocka7e24c12009-10-30 11:49:00 +0000103 private:
104 // Accessors.
105 inline State state() const;
106
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100107 inline Address* pc_address() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000108
109 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
110};
111
112
113#define STACK_FRAME_TYPE_LIST(V) \
114 V(ENTRY, EntryFrame) \
115 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
116 V(EXIT, ExitFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000117 V(JAVA_SCRIPT, JavaScriptFrame) \
118 V(INTERNAL, InternalFrame) \
119 V(CONSTRUCT, ConstructFrame) \
120 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
121
122
123// Abstract base class for all stack frames.
124class StackFrame BASE_EMBEDDED {
125 public:
126#define DECLARE_TYPE(type, ignore) type,
127 enum Type {
128 NONE = 0,
129 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
130 NUMBER_OF_TYPES
131 };
132#undef DECLARE_TYPE
133
134 // Opaque data type for identifying stack frames. Used extensively
135 // by the debugger.
Iain Merrick75681382010-08-19 15:07:18 +0100136 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
137 // has correct value range (see Issue 830 for more details).
138 enum Id {
139 ID_MIN_VALUE = kMinInt,
140 ID_MAX_VALUE = kMaxInt,
141 NO_ID = 0
142 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000143
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100144 struct State {
145 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
146 Address sp;
147 Address fp;
148 Address* pc_address;
149 };
150
Steve Block6ded16b2010-05-10 14:33:55 +0100151 // Copy constructor; it breaks the connection to host iterator.
152 StackFrame(const StackFrame& original) {
153 this->state_ = original.state_;
154 this->iterator_ = NULL;
155 }
156
Steve Blocka7e24c12009-10-30 11:49:00 +0000157 // Type testers.
158 bool is_entry() const { return type() == ENTRY; }
159 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
160 bool is_exit() const { return type() == EXIT; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000161 bool is_java_script() const { return type() == JAVA_SCRIPT; }
162 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
163 bool is_internal() const { return type() == INTERNAL; }
164 bool is_construct() const { return type() == CONSTRUCT; }
165 virtual bool is_standard() const { return false; }
166
167 // Accessors.
168 Address sp() const { return state_.sp; }
169 Address fp() const { return state_.fp; }
170 Address caller_sp() const { return GetCallerStackPointer(); }
171
172 Address pc() const { return *pc_address(); }
173 void set_pc(Address pc) { *pc_address() = pc; }
174
Steve Block6ded16b2010-05-10 14:33:55 +0100175 virtual void SetCallerFp(Address caller_fp) = 0;
176
Steve Blocka7e24c12009-10-30 11:49:00 +0000177 Address* pc_address() const { return state_.pc_address; }
178
179 // Get the id of this stack frame.
180 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
181
182 // Checks if this frame includes any stack handlers.
183 bool HasHandler() const;
184
185 // Get the type of this frame.
186 virtual Type type() const = 0;
187
188 // Get the code associated with this frame.
Iain Merrick75681382010-08-19 15:07:18 +0100189 // This method could be called during marking phase of GC.
190 virtual Code* unchecked_code() const = 0;
191
192 // Get the code associated with this frame.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100193 Code* code() const { return GetContainingCode(pc()); }
194
195 // Get the code object that contains the given pc.
196 Code* GetContainingCode(Address pc) const {
197 return PcToCodeCache::GetCacheEntry(pc)->code;
Iain Merrick75681382010-08-19 15:07:18 +0100198 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000199
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100200 virtual void Iterate(ObjectVisitor* v) const = 0;
201 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000202
Steve Blocka7e24c12009-10-30 11:49:00 +0000203
204 // Printing support.
205 enum PrintMode { OVERVIEW, DETAILS };
206 virtual void Print(StringStream* accumulator,
207 PrintMode mode,
208 int index) const { }
209
210 protected:
Steve Blocka7e24c12009-10-30 11:49:00 +0000211 explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
212 virtual ~StackFrame() { }
213
214 // Compute the stack pointer for the calling frame.
215 virtual Address GetCallerStackPointer() const = 0;
216
217 // Printing support.
218 static void PrintIndex(StringStream* accumulator,
219 PrintMode mode,
220 int index);
221
222 // Get the top handler from the current stack iterator.
223 inline StackHandler* top_handler() const;
224
225 // Compute the stack frame type for the given state.
226 static Type ComputeType(State* state);
227
228 private:
229 const StackFrameIterator* iterator_;
230 State state_;
231
232 // Fill in the state of the calling frame.
233 virtual void ComputeCallerState(State* state) const = 0;
234
235 // Get the type and the state of the calling frame.
236 virtual Type GetCallerState(State* state) const;
237
Steve Blocka7e24c12009-10-30 11:49:00 +0000238 friend class StackFrameIterator;
239 friend class StackHandlerIterator;
240 friend class SafeStackFrameIterator;
241
Steve Block6ded16b2010-05-10 14:33:55 +0100242 private:
243 void operator=(const StackFrame& original);
Steve Blocka7e24c12009-10-30 11:49:00 +0000244};
245
246
247// Entry frames are used to enter JavaScript execution from C.
248class EntryFrame: public StackFrame {
249 public:
250 virtual Type type() const { return ENTRY; }
251
Iain Merrick75681382010-08-19 15:07:18 +0100252 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000253
254 // Garbage collection support.
255 virtual void Iterate(ObjectVisitor* v) const;
256
257 static EntryFrame* cast(StackFrame* frame) {
258 ASSERT(frame->is_entry());
259 return static_cast<EntryFrame*>(frame);
260 }
Steve Block6ded16b2010-05-10 14:33:55 +0100261 virtual void SetCallerFp(Address caller_fp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000262
263 protected:
264 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
265
266 // The caller stack pointer for entry frames is always zero. The
267 // real information about the caller frame is available through the
268 // link to the top exit frame.
269 virtual Address GetCallerStackPointer() const { return 0; }
270
271 private:
272 virtual void ComputeCallerState(State* state) const;
273 virtual Type GetCallerState(State* state) const;
274
275 friend class StackFrameIterator;
276};
277
278
279class EntryConstructFrame: public EntryFrame {
280 public:
281 virtual Type type() const { return ENTRY_CONSTRUCT; }
282
Iain Merrick75681382010-08-19 15:07:18 +0100283 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000284
285 static EntryConstructFrame* cast(StackFrame* frame) {
286 ASSERT(frame->is_entry_construct());
287 return static_cast<EntryConstructFrame*>(frame);
288 }
289
290 protected:
291 explicit EntryConstructFrame(StackFrameIterator* iterator)
292 : EntryFrame(iterator) { }
293
294 private:
295 friend class StackFrameIterator;
296};
297
298
299// Exit frames are used to exit JavaScript execution and go to C.
300class ExitFrame: public StackFrame {
301 public:
302 virtual Type type() const { return EXIT; }
303
Iain Merrick75681382010-08-19 15:07:18 +0100304 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000305
Steve Blockd0582a62009-12-15 09:54:21 +0000306 Object*& code_slot() const;
307
Steve Blocka7e24c12009-10-30 11:49:00 +0000308 // Garbage collection support.
309 virtual void Iterate(ObjectVisitor* v) const;
310
Steve Block6ded16b2010-05-10 14:33:55 +0100311 virtual void SetCallerFp(Address caller_fp);
312
Steve Blocka7e24c12009-10-30 11:49:00 +0000313 static ExitFrame* cast(StackFrame* frame) {
314 ASSERT(frame->is_exit());
315 return static_cast<ExitFrame*>(frame);
316 }
317
318 // Compute the state and type of an exit frame given a frame
319 // pointer. Used when constructing the first stack frame seen by an
320 // iterator and the frames following entry frames.
321 static Type GetStateForFramePointer(Address fp, State* state);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100322 static Address ComputeStackPointer(Address fp);
323 static void FillState(Address fp, Address sp, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000324
325 protected:
326 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
327
328 virtual Address GetCallerStackPointer() const;
329
330 private:
331 virtual void ComputeCallerState(State* state) const;
332
333 friend class StackFrameIterator;
334};
335
336
Steve Blocka7e24c12009-10-30 11:49:00 +0000337class StandardFrame: public StackFrame {
338 public:
339 // Testers.
340 virtual bool is_standard() const { return true; }
341
342 // Accessors.
343 inline Object* context() const;
344
345 // Access the expressions in the stack frame including locals.
346 inline Object* GetExpression(int index) const;
347 inline void SetExpression(int index, Object* value);
348 int ComputeExpressionsCount() const;
349
Steve Block6ded16b2010-05-10 14:33:55 +0100350 virtual void SetCallerFp(Address caller_fp);
351
Steve Blocka7e24c12009-10-30 11:49:00 +0000352 static StandardFrame* cast(StackFrame* frame) {
353 ASSERT(frame->is_standard());
354 return static_cast<StandardFrame*>(frame);
355 }
356
357 protected:
358 explicit StandardFrame(StackFrameIterator* iterator)
359 : StackFrame(iterator) { }
360
361 virtual void ComputeCallerState(State* state) const;
362
363 // Accessors.
364 inline Address caller_fp() const;
365 inline Address caller_pc() const;
366
367 // Computes the address of the PC field in the standard frame given
368 // by the provided frame pointer.
369 static inline Address ComputePCAddress(Address fp);
370
371 // Iterate over expression stack including stack handlers, locals,
372 // and parts of the fixed part including context and code fields.
373 void IterateExpressions(ObjectVisitor* v) const;
374
375 // Returns the address of the n'th expression stack element.
376 Address GetExpressionAddress(int n) const;
377
378 // Determines if the n'th expression stack element is in a stack
379 // handler or not. Requires traversing all handlers in this frame.
380 bool IsExpressionInsideHandler(int n) const;
381
382 // Determines if the standard frame for the given frame pointer is
383 // an arguments adaptor frame.
384 static inline bool IsArgumentsAdaptorFrame(Address fp);
385
386 // Determines if the standard frame for the given frame pointer is a
387 // construct frame.
388 static inline bool IsConstructFrame(Address fp);
389
390 private:
391 friend class StackFrame;
Kristian Monsen25f61362010-05-21 11:50:48 +0100392 friend class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000393};
394
395
396class JavaScriptFrame: public StandardFrame {
397 public:
398 virtual Type type() const { return JAVA_SCRIPT; }
399
400 // Accessors.
401 inline Object* function() const;
402 inline Object* receiver() const;
403 inline void set_receiver(Object* value);
404
405 // Access the parameters.
406 Object* GetParameter(int index) const;
407 int ComputeParametersCount() const;
408
409 // Temporary way of getting access to the number of parameters
410 // passed on the stack by the caller. Once argument adaptor frames
411 // has been introduced on ARM, this number will always match the
412 // computed parameters count.
413 int GetProvidedParametersCount() const;
414
415 // Check if this frame is a constructor frame invoked through 'new'.
416 bool IsConstructor() const;
417
418 // Check if this frame has "adapted" arguments in the sense that the
419 // actual passed arguments are available in an arguments adaptor
420 // frame below it on the stack.
421 inline bool has_adapted_arguments() const;
422
423 // Garbage collection support.
424 virtual void Iterate(ObjectVisitor* v) const;
425
426 // Printing support.
427 virtual void Print(StringStream* accumulator,
428 PrintMode mode,
429 int index) const;
430
431 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100432 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000433
434 static JavaScriptFrame* cast(StackFrame* frame) {
435 ASSERT(frame->is_java_script());
436 return static_cast<JavaScriptFrame*>(frame);
437 }
438
439 protected:
440 explicit JavaScriptFrame(StackFrameIterator* iterator)
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100441 : StandardFrame(iterator) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000442
443 virtual Address GetCallerStackPointer() const;
444
Steve Blocka7e24c12009-10-30 11:49:00 +0000445 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000446 inline Object* function_slot_object() const;
447
448 friend class StackFrameIterator;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100449 friend class StackTracer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000450};
451
452
453// Arguments adaptor frames are automatically inserted below
454// JavaScript frames when the actual number of parameters does not
455// match the formal number of parameters.
456class ArgumentsAdaptorFrame: public JavaScriptFrame {
457 public:
458 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
459
460 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100461 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000462
463 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
464 ASSERT(frame->is_arguments_adaptor());
465 return static_cast<ArgumentsAdaptorFrame*>(frame);
466 }
467
468 // Printing support.
469 virtual void Print(StringStream* accumulator,
470 PrintMode mode,
471 int index) const;
472 protected:
473 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
474 : JavaScriptFrame(iterator) { }
475
476 virtual Address GetCallerStackPointer() const;
477
478 private:
479 friend class StackFrameIterator;
480};
481
482
483class InternalFrame: public StandardFrame {
484 public:
485 virtual Type type() const { return INTERNAL; }
486
487 // Garbage collection support.
488 virtual void Iterate(ObjectVisitor* v) const;
489
490 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100491 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000492
493 static InternalFrame* cast(StackFrame* frame) {
494 ASSERT(frame->is_internal());
495 return static_cast<InternalFrame*>(frame);
496 }
497
498 protected:
499 explicit InternalFrame(StackFrameIterator* iterator)
500 : StandardFrame(iterator) { }
501
502 virtual Address GetCallerStackPointer() const;
503
504 private:
505 friend class StackFrameIterator;
506};
507
508
509// Construct frames are special trampoline frames introduced to handle
510// function invocations through 'new'.
511class ConstructFrame: public InternalFrame {
512 public:
513 virtual Type type() const { return CONSTRUCT; }
514
515 static ConstructFrame* cast(StackFrame* frame) {
516 ASSERT(frame->is_construct());
517 return static_cast<ConstructFrame*>(frame);
518 }
519
520 protected:
521 explicit ConstructFrame(StackFrameIterator* iterator)
522 : InternalFrame(iterator) { }
523
524 private:
525 friend class StackFrameIterator;
526};
527
528
529class StackFrameIterator BASE_EMBEDDED {
530 public:
531 // An iterator that iterates over the current thread's stack.
532 StackFrameIterator();
533
534 // An iterator that iterates over a given thread's stack.
535 explicit StackFrameIterator(ThreadLocalTop* thread);
536
537 // An iterator that can start from a given FP address.
538 // If use_top, then work as usual, if fp isn't NULL, use it,
539 // otherwise, do nothing.
540 StackFrameIterator(bool use_top, Address fp, Address sp);
541
542 StackFrame* frame() const {
543 ASSERT(!done());
544 return frame_;
545 }
546
547 bool done() const { return frame_ == NULL; }
548 void Advance() { (this->*advance_)(); }
549
550 // Go back to the first frame.
551 void Reset();
552
553 private:
554#define DECLARE_SINGLETON(ignore, type) type type##_;
555 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
556#undef DECLARE_SINGLETON
557 StackFrame* frame_;
558 StackHandler* handler_;
559 ThreadLocalTop* thread_;
560 Address fp_;
561 Address sp_;
562 void (StackFrameIterator::*advance_)();
563
564 StackHandler* handler() const {
565 ASSERT(!done());
566 return handler_;
567 }
568
569 // Get the type-specific frame singleton in a given state.
570 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
571 // A helper function, can return a NULL pointer.
572 StackFrame* SingletonFor(StackFrame::Type type);
573
574 void AdvanceWithHandler();
575 void AdvanceWithoutHandler();
576
577 friend class StackFrame;
578 friend class SafeStackFrameIterator;
579 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
580};
581
582
583// Iterator that supports iterating through all JavaScript frames.
584template<typename Iterator>
585class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
586 public:
587 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
588
589 explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) :
590 iterator_(thread) {
591 if (!done()) Advance();
592 }
593
594 // Skip frames until the frame with the given id is reached.
595 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
596
597 JavaScriptFrameIteratorTemp(Address fp, Address sp,
598 Address low_bound, Address high_bound) :
599 iterator_(fp, sp, low_bound, high_bound) {
600 if (!done()) Advance();
601 }
602
603 inline JavaScriptFrame* frame() const;
604
605 bool done() const { return iterator_.done(); }
606 void Advance();
607
608 // Advance to the frame holding the arguments for the current
609 // frame. This only affects the current frame if it has adapted
610 // arguments.
611 void AdvanceToArgumentsFrame();
612
613 // Go back to the first frame.
614 void Reset();
615
616 private:
617 Iterator iterator_;
618};
619
620
621typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
622
623
624// NOTE: The stack trace frame iterator is an iterator that only
625// traverse proper JavaScript frames; that is JavaScript frames that
626// have proper JavaScript functions. This excludes the problematic
627// functions in runtime.js.
628class StackTraceFrameIterator: public JavaScriptFrameIterator {
629 public:
630 StackTraceFrameIterator();
631 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000632
633 private:
634 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000635};
636
637
638class SafeStackFrameIterator BASE_EMBEDDED {
639 public:
640 SafeStackFrameIterator(Address fp, Address sp,
641 Address low_bound, Address high_bound);
642
643 StackFrame* frame() const {
644 ASSERT(is_working_iterator_);
645 return iterator_.frame();
646 }
647
648 bool done() const { return iteration_done_ ? true : iterator_.done(); }
649
650 void Advance();
651 void Reset();
652
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100653 static bool is_active() { return active_count_ > 0; }
654
Steve Blocka7e24c12009-10-30 11:49:00 +0000655 static bool IsWithinBounds(
656 Address low_bound, Address high_bound, Address addr) {
657 return low_bound <= addr && addr <= high_bound;
658 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000659
660 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100661 class StackAddressValidator {
662 public:
663 StackAddressValidator(Address low_bound, Address high_bound)
664 : low_bound_(low_bound), high_bound_(high_bound) { }
665 bool IsValid(Address addr) const {
666 return IsWithinBounds(low_bound_, high_bound_, addr);
667 }
668 private:
669 Address low_bound_;
670 Address high_bound_;
671 };
672
673 class ExitFrameValidator {
674 public:
675 explicit ExitFrameValidator(const StackAddressValidator& validator)
676 : validator_(validator) { }
677 ExitFrameValidator(Address low_bound, Address high_bound)
678 : validator_(low_bound, high_bound) { }
679 bool IsValidFP(Address fp);
680 private:
681 StackAddressValidator validator_;
682 };
683
Steve Blocka7e24c12009-10-30 11:49:00 +0000684 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100685 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000686 }
687 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
688 bool IsValidFrame(StackFrame* frame) const;
689 bool IsValidCaller(StackFrame* frame);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100690 static bool IsValidTop(Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000691
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100692 // This is a nasty hack to make sure the active count is incremented
693 // before the constructor for the embedded iterator is invoked. This
694 // is needed because the constructor will start looking at frames
695 // right away and we need to make sure it doesn't start inspecting
696 // heap objects.
697 class ActiveCountMaintainer BASE_EMBEDDED {
698 public:
699 ActiveCountMaintainer() { active_count_++; }
700 ~ActiveCountMaintainer() { active_count_--; }
701 };
702
703 ActiveCountMaintainer maintainer_;
704 static int active_count_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100705 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000706 const bool is_valid_top_;
707 const bool is_valid_fp_;
708 const bool is_working_iterator_;
709 bool iteration_done_;
710 StackFrameIterator iterator_;
711};
712
713
714#ifdef ENABLE_LOGGING_AND_PROFILING
715typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
716 SafeJavaScriptFrameIterator;
717
718
719class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
720 public:
721 explicit SafeStackTraceFrameIterator(Address fp, Address sp,
722 Address low_bound, Address high_bound);
723 void Advance();
724};
725#endif
726
727
728class StackFrameLocator BASE_EMBEDDED {
729 public:
730 // Find the nth JavaScript frame on the stack. The caller must
731 // guarantee that such a frame exists.
732 JavaScriptFrame* FindJavaScriptFrame(int n);
733
734 private:
735 StackFrameIterator iterator_;
736};
737
738
Steve Block6ded16b2010-05-10 14:33:55 +0100739// Reads all frames on the current stack and copies them into the current
740// zone memory.
741Vector<StackFrame*> CreateStackMap();
742
Steve Blocka7e24c12009-10-30 11:49:00 +0000743} } // namespace v8::internal
744
745#endif // V8_FRAMES_H_