blob: 778f9d2435e0d2cba42d45e9f012d9e23743050f [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;
Ben Murdochb0fe1622011-05-05 13:52:32 +010054 uint8_t* safepoint_entry;
Kristian Monsen80d68ea2010-09-08 11:05:35 +010055 };
56
57 static PcToCodeCacheEntry* cache(int index) {
58 return &cache_[index];
59 }
60
61 static Code* GcSafeFindCodeForPc(Address pc);
62 static Code* GcSafeCastToCode(HeapObject* object, Address pc);
63
64 static void FlushPcToCodeCache() {
65 memset(&cache_[0], 0, sizeof(cache_));
66 }
67
68 static PcToCodeCacheEntry* GetCacheEntry(Address pc);
69
70 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +010071 static const int kPcToCodeCacheSize = 1024;
Kristian Monsen80d68ea2010-09-08 11:05:35 +010072 static PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
73};
74
75
Steve Blocka7e24c12009-10-30 11:49:00 +000076class StackHandler BASE_EMBEDDED {
77 public:
78 enum State {
79 ENTRY,
80 TRY_CATCH,
81 TRY_FINALLY
82 };
83
84 // Get the address of this stack handler.
85 inline Address address() const;
86
87 // Get the next stack handler in the chain.
88 inline StackHandler* next() const;
89
90 // Tells whether the given address is inside this handler.
91 inline bool includes(Address address) const;
92
93 // Garbage collection support.
Kristian Monsen80d68ea2010-09-08 11:05:35 +010094 inline void Iterate(ObjectVisitor* v, Code* holder) const;
Steve Blocka7e24c12009-10-30 11:49:00 +000095
96 // Conversion support.
97 static inline StackHandler* FromAddress(Address address);
98
99 // Testers
100 bool is_entry() { return state() == ENTRY; }
101 bool is_try_catch() { return state() == TRY_CATCH; }
102 bool is_try_finally() { return state() == TRY_FINALLY; }
103
Steve Blocka7e24c12009-10-30 11:49:00 +0000104 private:
105 // Accessors.
106 inline State state() const;
107
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100108 inline Address* pc_address() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000109
110 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
111};
112
113
114#define STACK_FRAME_TYPE_LIST(V) \
115 V(ENTRY, EntryFrame) \
116 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
117 V(EXIT, ExitFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000118 V(JAVA_SCRIPT, JavaScriptFrame) \
Ben Murdochb0fe1622011-05-05 13:52:32 +0100119 V(OPTIMIZED, OptimizedFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000120 V(INTERNAL, InternalFrame) \
121 V(CONSTRUCT, ConstructFrame) \
122 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
123
124
125// Abstract base class for all stack frames.
126class StackFrame BASE_EMBEDDED {
127 public:
128#define DECLARE_TYPE(type, ignore) type,
129 enum Type {
130 NONE = 0,
131 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
132 NUMBER_OF_TYPES
133 };
134#undef DECLARE_TYPE
135
136 // Opaque data type for identifying stack frames. Used extensively
137 // by the debugger.
Iain Merrick75681382010-08-19 15:07:18 +0100138 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
139 // has correct value range (see Issue 830 for more details).
140 enum Id {
141 ID_MIN_VALUE = kMinInt,
142 ID_MAX_VALUE = kMaxInt,
143 NO_ID = 0
144 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000145
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100146 struct State {
147 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
148 Address sp;
149 Address fp;
150 Address* pc_address;
151 };
152
Steve Block6ded16b2010-05-10 14:33:55 +0100153 // Copy constructor; it breaks the connection to host iterator.
154 StackFrame(const StackFrame& original) {
155 this->state_ = original.state_;
156 this->iterator_ = NULL;
157 }
158
Steve Blocka7e24c12009-10-30 11:49:00 +0000159 // Type testers.
160 bool is_entry() const { return type() == ENTRY; }
161 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
162 bool is_exit() const { return type() == EXIT; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100163 bool is_optimized() const { return type() == OPTIMIZED; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000164 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
165 bool is_internal() const { return type() == INTERNAL; }
166 bool is_construct() const { return type() == CONSTRUCT; }
167 virtual bool is_standard() const { return false; }
168
Ben Murdochb0fe1622011-05-05 13:52:32 +0100169 bool is_java_script() const {
170 Type type = this->type();
171 return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
172 }
173
Steve Blocka7e24c12009-10-30 11:49:00 +0000174 // Accessors.
175 Address sp() const { return state_.sp; }
176 Address fp() const { return state_.fp; }
177 Address caller_sp() const { return GetCallerStackPointer(); }
178
179 Address pc() const { return *pc_address(); }
180 void set_pc(Address pc) { *pc_address() = pc; }
181
Steve Block6ded16b2010-05-10 14:33:55 +0100182 virtual void SetCallerFp(Address caller_fp) = 0;
183
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 Address* pc_address() const { return state_.pc_address; }
185
186 // Get the id of this stack frame.
187 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
188
189 // Checks if this frame includes any stack handlers.
190 bool HasHandler() const;
191
192 // Get the type of this frame.
193 virtual Type type() const = 0;
194
195 // Get the code associated with this frame.
Iain Merrick75681382010-08-19 15:07:18 +0100196 // This method could be called during marking phase of GC.
197 virtual Code* unchecked_code() const = 0;
198
199 // Get the code associated with this frame.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100200 Code* code() const { return GetContainingCode(pc()); }
201
202 // Get the code object that contains the given pc.
Ben Murdochb0fe1622011-05-05 13:52:32 +0100203 static Code* GetContainingCode(Address pc) {
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100204 return PcToCodeCache::GetCacheEntry(pc)->code;
Iain Merrick75681382010-08-19 15:07:18 +0100205 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000206
Ben Murdochb0fe1622011-05-05 13:52:32 +0100207 // Get the code object containing the given pc and fill in the
208 // safepoint entry and the number of stack slots. The pc must be at
209 // a safepoint.
210 static Code* GetSafepointData(Address pc,
211 uint8_t** safepoint_entry,
212 unsigned* stack_slots);
213
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100214 virtual void Iterate(ObjectVisitor* v) const = 0;
215 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000216
Steve Blocka7e24c12009-10-30 11:49:00 +0000217
218 // Printing support.
219 enum PrintMode { OVERVIEW, DETAILS };
220 virtual void Print(StringStream* accumulator,
221 PrintMode mode,
222 int index) const { }
223
224 protected:
Steve Blocka7e24c12009-10-30 11:49:00 +0000225 explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
226 virtual ~StackFrame() { }
227
228 // Compute the stack pointer for the calling frame.
229 virtual Address GetCallerStackPointer() const = 0;
230
231 // Printing support.
232 static void PrintIndex(StringStream* accumulator,
233 PrintMode mode,
234 int index);
235
236 // Get the top handler from the current stack iterator.
237 inline StackHandler* top_handler() const;
238
239 // Compute the stack frame type for the given state.
240 static Type ComputeType(State* state);
241
242 private:
243 const StackFrameIterator* iterator_;
244 State state_;
245
246 // Fill in the state of the calling frame.
247 virtual void ComputeCallerState(State* state) const = 0;
248
249 // Get the type and the state of the calling frame.
250 virtual Type GetCallerState(State* state) const;
251
Steve Blocka7e24c12009-10-30 11:49:00 +0000252 friend class StackFrameIterator;
253 friend class StackHandlerIterator;
254 friend class SafeStackFrameIterator;
255
Steve Block6ded16b2010-05-10 14:33:55 +0100256 private:
257 void operator=(const StackFrame& original);
Steve Blocka7e24c12009-10-30 11:49:00 +0000258};
259
260
261// Entry frames are used to enter JavaScript execution from C.
262class EntryFrame: public StackFrame {
263 public:
264 virtual Type type() const { return ENTRY; }
265
Iain Merrick75681382010-08-19 15:07:18 +0100266 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000267
268 // Garbage collection support.
269 virtual void Iterate(ObjectVisitor* v) const;
270
271 static EntryFrame* cast(StackFrame* frame) {
272 ASSERT(frame->is_entry());
273 return static_cast<EntryFrame*>(frame);
274 }
Steve Block6ded16b2010-05-10 14:33:55 +0100275 virtual void SetCallerFp(Address caller_fp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000276
277 protected:
278 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
279
280 // The caller stack pointer for entry frames is always zero. The
281 // real information about the caller frame is available through the
282 // link to the top exit frame.
283 virtual Address GetCallerStackPointer() const { return 0; }
284
285 private:
286 virtual void ComputeCallerState(State* state) const;
287 virtual Type GetCallerState(State* state) const;
288
289 friend class StackFrameIterator;
290};
291
292
293class EntryConstructFrame: public EntryFrame {
294 public:
295 virtual Type type() const { return ENTRY_CONSTRUCT; }
296
Iain Merrick75681382010-08-19 15:07:18 +0100297 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000298
299 static EntryConstructFrame* cast(StackFrame* frame) {
300 ASSERT(frame->is_entry_construct());
301 return static_cast<EntryConstructFrame*>(frame);
302 }
303
304 protected:
305 explicit EntryConstructFrame(StackFrameIterator* iterator)
306 : EntryFrame(iterator) { }
307
308 private:
309 friend class StackFrameIterator;
310};
311
312
313// Exit frames are used to exit JavaScript execution and go to C.
314class ExitFrame: public StackFrame {
315 public:
316 virtual Type type() const { return EXIT; }
317
Iain Merrick75681382010-08-19 15:07:18 +0100318 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000319
Steve Blockd0582a62009-12-15 09:54:21 +0000320 Object*& code_slot() const;
321
Steve Blocka7e24c12009-10-30 11:49:00 +0000322 // Garbage collection support.
323 virtual void Iterate(ObjectVisitor* v) const;
324
Steve Block6ded16b2010-05-10 14:33:55 +0100325 virtual void SetCallerFp(Address caller_fp);
326
Steve Blocka7e24c12009-10-30 11:49:00 +0000327 static ExitFrame* cast(StackFrame* frame) {
328 ASSERT(frame->is_exit());
329 return static_cast<ExitFrame*>(frame);
330 }
331
332 // Compute the state and type of an exit frame given a frame
333 // pointer. Used when constructing the first stack frame seen by an
334 // iterator and the frames following entry frames.
335 static Type GetStateForFramePointer(Address fp, State* state);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100336 static Address ComputeStackPointer(Address fp);
337 static void FillState(Address fp, Address sp, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000338
339 protected:
340 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
341
342 virtual Address GetCallerStackPointer() const;
343
344 private:
345 virtual void ComputeCallerState(State* state) const;
346
347 friend class StackFrameIterator;
348};
349
350
Steve Blocka7e24c12009-10-30 11:49:00 +0000351class StandardFrame: public StackFrame {
352 public:
353 // Testers.
354 virtual bool is_standard() const { return true; }
355
356 // Accessors.
357 inline Object* context() const;
358
359 // Access the expressions in the stack frame including locals.
360 inline Object* GetExpression(int index) const;
361 inline void SetExpression(int index, Object* value);
362 int ComputeExpressionsCount() const;
363
Steve Block6ded16b2010-05-10 14:33:55 +0100364 virtual void SetCallerFp(Address caller_fp);
365
Steve Blocka7e24c12009-10-30 11:49:00 +0000366 static StandardFrame* cast(StackFrame* frame) {
367 ASSERT(frame->is_standard());
368 return static_cast<StandardFrame*>(frame);
369 }
370
371 protected:
372 explicit StandardFrame(StackFrameIterator* iterator)
373 : StackFrame(iterator) { }
374
375 virtual void ComputeCallerState(State* state) const;
376
377 // Accessors.
378 inline Address caller_fp() const;
379 inline Address caller_pc() const;
380
381 // Computes the address of the PC field in the standard frame given
382 // by the provided frame pointer.
383 static inline Address ComputePCAddress(Address fp);
384
385 // Iterate over expression stack including stack handlers, locals,
386 // and parts of the fixed part including context and code fields.
387 void IterateExpressions(ObjectVisitor* v) const;
388
389 // Returns the address of the n'th expression stack element.
390 Address GetExpressionAddress(int n) const;
391
392 // Determines if the n'th expression stack element is in a stack
393 // handler or not. Requires traversing all handlers in this frame.
394 bool IsExpressionInsideHandler(int n) const;
395
396 // Determines if the standard frame for the given frame pointer is
397 // an arguments adaptor frame.
398 static inline bool IsArgumentsAdaptorFrame(Address fp);
399
400 // Determines if the standard frame for the given frame pointer is a
401 // construct frame.
402 static inline bool IsConstructFrame(Address fp);
403
404 private:
405 friend class StackFrame;
Kristian Monsen25f61362010-05-21 11:50:48 +0100406 friend class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000407};
408
409
Ben Murdochb0fe1622011-05-05 13:52:32 +0100410class FrameSummary BASE_EMBEDDED {
411 public:
412 FrameSummary(Object* receiver,
413 JSFunction* function,
414 Code* code,
415 int offset,
416 bool is_constructor)
417 : receiver_(receiver),
418 function_(function),
419 code_(code),
420 offset_(offset),
421 is_constructor_(is_constructor) { }
422 Handle<Object> receiver() { return receiver_; }
423 Handle<JSFunction> function() { return function_; }
424 Handle<Code> code() { return code_; }
425 Address pc() { return reinterpret_cast<Address>(*code_) + offset_; }
426 int offset() { return offset_; }
427 bool is_constructor() { return is_constructor_; }
428
429 void Print();
430
431 private:
432 Handle<Object> receiver_;
433 Handle<JSFunction> function_;
434 Handle<Code> code_;
435 int offset_;
436 bool is_constructor_;
437};
438
439
Steve Blocka7e24c12009-10-30 11:49:00 +0000440class JavaScriptFrame: public StandardFrame {
441 public:
442 virtual Type type() const { return JAVA_SCRIPT; }
443
444 // Accessors.
445 inline Object* function() const;
446 inline Object* receiver() const;
447 inline void set_receiver(Object* value);
448
449 // Access the parameters.
450 Object* GetParameter(int index) const;
451 int ComputeParametersCount() const;
452
453 // Temporary way of getting access to the number of parameters
454 // passed on the stack by the caller. Once argument adaptor frames
455 // has been introduced on ARM, this number will always match the
456 // computed parameters count.
457 int GetProvidedParametersCount() const;
458
459 // Check if this frame is a constructor frame invoked through 'new'.
460 bool IsConstructor() const;
461
462 // Check if this frame has "adapted" arguments in the sense that the
463 // actual passed arguments are available in an arguments adaptor
464 // frame below it on the stack.
465 inline bool has_adapted_arguments() const;
466
467 // Garbage collection support.
468 virtual void Iterate(ObjectVisitor* v) const;
469
470 // Printing support.
471 virtual void Print(StringStream* accumulator,
472 PrintMode mode,
473 int index) const;
474
475 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100476 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000477
Ben Murdochb0fe1622011-05-05 13:52:32 +0100478 // Return a list with JSFunctions of this frame.
479 virtual void GetFunctions(List<JSFunction*>* functions);
480
481 // Build a list with summaries for this frame including all inlined frames.
482 virtual void Summarize(List<FrameSummary>* frames);
483
Steve Blocka7e24c12009-10-30 11:49:00 +0000484 static JavaScriptFrame* cast(StackFrame* frame) {
485 ASSERT(frame->is_java_script());
486 return static_cast<JavaScriptFrame*>(frame);
487 }
488
489 protected:
490 explicit JavaScriptFrame(StackFrameIterator* iterator)
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100491 : StandardFrame(iterator) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000492
493 virtual Address GetCallerStackPointer() const;
494
Ben Murdochb0fe1622011-05-05 13:52:32 +0100495 // Garbage collection support. Iterates over incoming arguments,
496 // receiver, and any callee-saved registers.
497 void IterateArguments(ObjectVisitor* v) const;
498
Steve Blocka7e24c12009-10-30 11:49:00 +0000499 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000500 inline Object* function_slot_object() const;
501
502 friend class StackFrameIterator;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100503 friend class StackTracer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000504};
505
506
Ben Murdochb0fe1622011-05-05 13:52:32 +0100507class OptimizedFrame : public JavaScriptFrame {
508 public:
509 virtual Type type() const { return OPTIMIZED; }
510
511 // GC support.
512 virtual void Iterate(ObjectVisitor* v) const;
513
514 // Return a list with JSFunctions of this frame.
515 // The functions are ordered bottom-to-top (i.e. functions.last()
516 // is the top-most activation)
517 virtual void GetFunctions(List<JSFunction*>* functions);
518
519 virtual void Summarize(List<FrameSummary>* frames);
520
521 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
522
523 protected:
524 explicit OptimizedFrame(StackFrameIterator* iterator)
525 : JavaScriptFrame(iterator) { }
526
527 private:
528 friend class StackFrameIterator;
529};
530
531
Steve Blocka7e24c12009-10-30 11:49:00 +0000532// Arguments adaptor frames are automatically inserted below
533// JavaScript frames when the actual number of parameters does not
534// match the formal number of parameters.
535class ArgumentsAdaptorFrame: public JavaScriptFrame {
536 public:
537 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
538
539 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100540 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000541
542 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
543 ASSERT(frame->is_arguments_adaptor());
544 return static_cast<ArgumentsAdaptorFrame*>(frame);
545 }
546
547 // Printing support.
548 virtual void Print(StringStream* accumulator,
549 PrintMode mode,
550 int index) const;
551 protected:
552 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
553 : JavaScriptFrame(iterator) { }
554
555 virtual Address GetCallerStackPointer() const;
556
557 private:
558 friend class StackFrameIterator;
559};
560
561
562class InternalFrame: public StandardFrame {
563 public:
564 virtual Type type() const { return INTERNAL; }
565
566 // Garbage collection support.
567 virtual void Iterate(ObjectVisitor* v) const;
568
569 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100570 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000571
572 static InternalFrame* cast(StackFrame* frame) {
573 ASSERT(frame->is_internal());
574 return static_cast<InternalFrame*>(frame);
575 }
576
577 protected:
578 explicit InternalFrame(StackFrameIterator* iterator)
579 : StandardFrame(iterator) { }
580
581 virtual Address GetCallerStackPointer() const;
582
583 private:
584 friend class StackFrameIterator;
585};
586
587
588// Construct frames are special trampoline frames introduced to handle
589// function invocations through 'new'.
590class ConstructFrame: public InternalFrame {
591 public:
592 virtual Type type() const { return CONSTRUCT; }
593
594 static ConstructFrame* cast(StackFrame* frame) {
595 ASSERT(frame->is_construct());
596 return static_cast<ConstructFrame*>(frame);
597 }
598
599 protected:
600 explicit ConstructFrame(StackFrameIterator* iterator)
601 : InternalFrame(iterator) { }
602
603 private:
604 friend class StackFrameIterator;
605};
606
607
608class StackFrameIterator BASE_EMBEDDED {
609 public:
610 // An iterator that iterates over the current thread's stack.
611 StackFrameIterator();
612
613 // An iterator that iterates over a given thread's stack.
614 explicit StackFrameIterator(ThreadLocalTop* thread);
615
616 // An iterator that can start from a given FP address.
617 // If use_top, then work as usual, if fp isn't NULL, use it,
618 // otherwise, do nothing.
619 StackFrameIterator(bool use_top, Address fp, Address sp);
620
621 StackFrame* frame() const {
622 ASSERT(!done());
623 return frame_;
624 }
625
626 bool done() const { return frame_ == NULL; }
627 void Advance() { (this->*advance_)(); }
628
629 // Go back to the first frame.
630 void Reset();
631
632 private:
633#define DECLARE_SINGLETON(ignore, type) type type##_;
634 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
635#undef DECLARE_SINGLETON
636 StackFrame* frame_;
637 StackHandler* handler_;
638 ThreadLocalTop* thread_;
639 Address fp_;
640 Address sp_;
641 void (StackFrameIterator::*advance_)();
642
643 StackHandler* handler() const {
644 ASSERT(!done());
645 return handler_;
646 }
647
648 // Get the type-specific frame singleton in a given state.
649 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
650 // A helper function, can return a NULL pointer.
651 StackFrame* SingletonFor(StackFrame::Type type);
652
653 void AdvanceWithHandler();
654 void AdvanceWithoutHandler();
655
656 friend class StackFrame;
657 friend class SafeStackFrameIterator;
658 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
659};
660
661
662// Iterator that supports iterating through all JavaScript frames.
663template<typename Iterator>
664class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
665 public:
666 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
667
668 explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) :
669 iterator_(thread) {
670 if (!done()) Advance();
671 }
672
673 // Skip frames until the frame with the given id is reached.
674 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
675
676 JavaScriptFrameIteratorTemp(Address fp, Address sp,
677 Address low_bound, Address high_bound) :
678 iterator_(fp, sp, low_bound, high_bound) {
679 if (!done()) Advance();
680 }
681
682 inline JavaScriptFrame* frame() const;
683
684 bool done() const { return iterator_.done(); }
685 void Advance();
686
687 // Advance to the frame holding the arguments for the current
688 // frame. This only affects the current frame if it has adapted
689 // arguments.
690 void AdvanceToArgumentsFrame();
691
692 // Go back to the first frame.
693 void Reset();
694
695 private:
696 Iterator iterator_;
697};
698
699
700typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
701
702
703// NOTE: The stack trace frame iterator is an iterator that only
704// traverse proper JavaScript frames; that is JavaScript frames that
705// have proper JavaScript functions. This excludes the problematic
706// functions in runtime.js.
707class StackTraceFrameIterator: public JavaScriptFrameIterator {
708 public:
709 StackTraceFrameIterator();
710 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000711
712 private:
713 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000714};
715
716
717class SafeStackFrameIterator BASE_EMBEDDED {
718 public:
719 SafeStackFrameIterator(Address fp, Address sp,
720 Address low_bound, Address high_bound);
721
722 StackFrame* frame() const {
723 ASSERT(is_working_iterator_);
724 return iterator_.frame();
725 }
726
727 bool done() const { return iteration_done_ ? true : iterator_.done(); }
728
729 void Advance();
730 void Reset();
731
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100732 static bool is_active() { return active_count_ > 0; }
733
Steve Blocka7e24c12009-10-30 11:49:00 +0000734 static bool IsWithinBounds(
735 Address low_bound, Address high_bound, Address addr) {
736 return low_bound <= addr && addr <= high_bound;
737 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000738
739 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100740 class StackAddressValidator {
741 public:
742 StackAddressValidator(Address low_bound, Address high_bound)
743 : low_bound_(low_bound), high_bound_(high_bound) { }
744 bool IsValid(Address addr) const {
745 return IsWithinBounds(low_bound_, high_bound_, addr);
746 }
747 private:
748 Address low_bound_;
749 Address high_bound_;
750 };
751
752 class ExitFrameValidator {
753 public:
754 explicit ExitFrameValidator(const StackAddressValidator& validator)
755 : validator_(validator) { }
756 ExitFrameValidator(Address low_bound, Address high_bound)
757 : validator_(low_bound, high_bound) { }
758 bool IsValidFP(Address fp);
759 private:
760 StackAddressValidator validator_;
761 };
762
Steve Blocka7e24c12009-10-30 11:49:00 +0000763 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100764 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000765 }
766 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
767 bool IsValidFrame(StackFrame* frame) const;
768 bool IsValidCaller(StackFrame* frame);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100769 static bool IsValidTop(Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000770
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100771 // This is a nasty hack to make sure the active count is incremented
772 // before the constructor for the embedded iterator is invoked. This
773 // is needed because the constructor will start looking at frames
774 // right away and we need to make sure it doesn't start inspecting
775 // heap objects.
776 class ActiveCountMaintainer BASE_EMBEDDED {
777 public:
778 ActiveCountMaintainer() { active_count_++; }
779 ~ActiveCountMaintainer() { active_count_--; }
780 };
781
782 ActiveCountMaintainer maintainer_;
783 static int active_count_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100784 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000785 const bool is_valid_top_;
786 const bool is_valid_fp_;
787 const bool is_working_iterator_;
788 bool iteration_done_;
789 StackFrameIterator iterator_;
790};
791
792
793#ifdef ENABLE_LOGGING_AND_PROFILING
794typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
795 SafeJavaScriptFrameIterator;
796
797
798class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
799 public:
800 explicit SafeStackTraceFrameIterator(Address fp, Address sp,
801 Address low_bound, Address high_bound);
802 void Advance();
803};
804#endif
805
806
807class StackFrameLocator BASE_EMBEDDED {
808 public:
809 // Find the nth JavaScript frame on the stack. The caller must
810 // guarantee that such a frame exists.
811 JavaScriptFrame* FindJavaScriptFrame(int n);
812
813 private:
814 StackFrameIterator iterator_;
815};
816
817
Steve Block6ded16b2010-05-10 14:33:55 +0100818// Reads all frames on the current stack and copies them into the current
819// zone memory.
820Vector<StackFrame*> CreateStackMap();
821
Steve Blocka7e24c12009-10-30 11:49:00 +0000822} } // namespace v8::internal
823
824#endif // V8_FRAMES_H_