blob: bee95ccbf1d2582c448a344280429cc6e07f7bdf [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
Steve Block44f0eee2011-05-26 01:26:41 +010031#include "handles.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010032#include "safepoint-table.h"
33
Steve Blocka7e24c12009-10-30 11:49:00 +000034namespace v8 {
35namespace internal {
36
37typedef uint32_t RegList;
38
39// Get the number of registers in a given register list.
40int NumRegs(RegList list);
41
42// Return the code of the n-th saved register available to JavaScript.
43int JSCallerSavedCode(int n);
44
45
46// Forward declarations.
47class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +000048class ThreadLocalTop;
Steve Block44f0eee2011-05-26 01:26:41 +010049class Isolate;
Steve Blocka7e24c12009-10-30 11:49:00 +000050
Steve Block44f0eee2011-05-26 01:26:41 +010051class PcToCodeCache {
Kristian Monsen80d68ea2010-09-08 11:05:35 +010052 public:
53 struct PcToCodeCacheEntry {
54 Address pc;
55 Code* code;
Ben Murdochb8e0da22011-05-16 14:20:40 +010056 SafepointEntry safepoint_entry;
Kristian Monsen80d68ea2010-09-08 11:05:35 +010057 };
58
Steve Block44f0eee2011-05-26 01:26:41 +010059 explicit PcToCodeCache(Isolate* isolate) : isolate_(isolate) {
60 Flush();
Kristian Monsen80d68ea2010-09-08 11:05:35 +010061 }
62
Steve Block44f0eee2011-05-26 01:26:41 +010063 Code* GcSafeFindCodeForPc(Address pc);
64 Code* GcSafeCastToCode(HeapObject* object, Address pc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010065
Steve Block44f0eee2011-05-26 01:26:41 +010066 void Flush() {
Kristian Monsen80d68ea2010-09-08 11:05:35 +010067 memset(&cache_[0], 0, sizeof(cache_));
68 }
69
Steve Block44f0eee2011-05-26 01:26:41 +010070 PcToCodeCacheEntry* GetCacheEntry(Address pc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010071
72 private:
Steve Block44f0eee2011-05-26 01:26:41 +010073 PcToCodeCacheEntry* cache(int index) { return &cache_[index]; }
74
75 Isolate* isolate_;
76
Kristian Monsen0d5e1162010-09-30 15:31:59 +010077 static const int kPcToCodeCacheSize = 1024;
Steve Block44f0eee2011-05-26 01:26:41 +010078 PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
79
80 DISALLOW_COPY_AND_ASSIGN(PcToCodeCache);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010081};
82
83
Steve Blocka7e24c12009-10-30 11:49:00 +000084class StackHandler BASE_EMBEDDED {
85 public:
86 enum State {
87 ENTRY,
88 TRY_CATCH,
89 TRY_FINALLY
90 };
91
92 // Get the address of this stack handler.
93 inline Address address() const;
94
95 // Get the next stack handler in the chain.
96 inline StackHandler* next() const;
97
98 // Tells whether the given address is inside this handler.
99 inline bool includes(Address address) const;
100
101 // Garbage collection support.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100102 inline void Iterate(ObjectVisitor* v, Code* holder) const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000103
104 // Conversion support.
105 static inline StackHandler* FromAddress(Address address);
106
107 // Testers
108 bool is_entry() { return state() == ENTRY; }
109 bool is_try_catch() { return state() == TRY_CATCH; }
110 bool is_try_finally() { return state() == TRY_FINALLY; }
111
Steve Blocka7e24c12009-10-30 11:49:00 +0000112 private:
113 // Accessors.
114 inline State state() const;
115
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100116 inline Address* pc_address() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000117
118 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
119};
120
121
122#define STACK_FRAME_TYPE_LIST(V) \
123 V(ENTRY, EntryFrame) \
124 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
125 V(EXIT, ExitFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000126 V(JAVA_SCRIPT, JavaScriptFrame) \
Ben Murdochb0fe1622011-05-05 13:52:32 +0100127 V(OPTIMIZED, OptimizedFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000128 V(INTERNAL, InternalFrame) \
129 V(CONSTRUCT, ConstructFrame) \
130 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
131
132
133// Abstract base class for all stack frames.
134class StackFrame BASE_EMBEDDED {
135 public:
136#define DECLARE_TYPE(type, ignore) type,
137 enum Type {
138 NONE = 0,
139 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
140 NUMBER_OF_TYPES
141 };
142#undef DECLARE_TYPE
143
144 // Opaque data type for identifying stack frames. Used extensively
145 // by the debugger.
Iain Merrick75681382010-08-19 15:07:18 +0100146 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
147 // has correct value range (see Issue 830 for more details).
148 enum Id {
149 ID_MIN_VALUE = kMinInt,
150 ID_MAX_VALUE = kMaxInt,
151 NO_ID = 0
152 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000153
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100154 struct State {
155 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
156 Address sp;
157 Address fp;
158 Address* pc_address;
159 };
160
Steve Block6ded16b2010-05-10 14:33:55 +0100161 // Copy constructor; it breaks the connection to host iterator.
162 StackFrame(const StackFrame& original) {
163 this->state_ = original.state_;
164 this->iterator_ = NULL;
165 }
166
Steve Blocka7e24c12009-10-30 11:49:00 +0000167 // Type testers.
168 bool is_entry() const { return type() == ENTRY; }
169 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
170 bool is_exit() const { return type() == EXIT; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100171 bool is_optimized() const { return type() == OPTIMIZED; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000172 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
173 bool is_internal() const { return type() == INTERNAL; }
174 bool is_construct() const { return type() == CONSTRUCT; }
175 virtual bool is_standard() const { return false; }
176
Ben Murdochb0fe1622011-05-05 13:52:32 +0100177 bool is_java_script() const {
178 Type type = this->type();
179 return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
180 }
181
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 // Accessors.
183 Address sp() const { return state_.sp; }
184 Address fp() const { return state_.fp; }
185 Address caller_sp() const { return GetCallerStackPointer(); }
186
187 Address pc() const { return *pc_address(); }
188 void set_pc(Address pc) { *pc_address() = pc; }
189
Steve Block6ded16b2010-05-10 14:33:55 +0100190 virtual void SetCallerFp(Address caller_fp) = 0;
191
Steve Blocka7e24c12009-10-30 11:49:00 +0000192 Address* pc_address() const { return state_.pc_address; }
193
194 // Get the id of this stack frame.
195 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
196
197 // Checks if this frame includes any stack handlers.
198 bool HasHandler() const;
199
200 // Get the type of this frame.
201 virtual Type type() const = 0;
202
203 // Get the code associated with this frame.
Iain Merrick75681382010-08-19 15:07:18 +0100204 // This method could be called during marking phase of GC.
205 virtual Code* unchecked_code() const = 0;
206
207 // Get the code associated with this frame.
Steve Block44f0eee2011-05-26 01:26:41 +0100208 Code* LookupCode(Isolate* isolate) const {
209 return GetContainingCode(isolate, pc());
210 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100211
212 // Get the code object that contains the given pc.
Steve Block44f0eee2011-05-26 01:26:41 +0100213 static inline Code* GetContainingCode(Isolate* isolate, Address pc);
Steve Blocka7e24c12009-10-30 11:49:00 +0000214
Ben Murdochb0fe1622011-05-05 13:52:32 +0100215 // Get the code object containing the given pc and fill in the
216 // safepoint entry and the number of stack slots. The pc must be at
217 // a safepoint.
218 static Code* GetSafepointData(Address pc,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100219 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100220 unsigned* stack_slots);
221
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100222 virtual void Iterate(ObjectVisitor* v) const = 0;
223 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000224
Steve Blocka7e24c12009-10-30 11:49:00 +0000225
226 // Printing support.
227 enum PrintMode { OVERVIEW, DETAILS };
228 virtual void Print(StringStream* accumulator,
229 PrintMode mode,
230 int index) const { }
231
232 protected:
Steve Blocka7e24c12009-10-30 11:49:00 +0000233 explicit StackFrame(StackFrameIterator* iterator) : iterator_(iterator) { }
234 virtual ~StackFrame() { }
235
236 // Compute the stack pointer for the calling frame.
237 virtual Address GetCallerStackPointer() const = 0;
238
239 // Printing support.
240 static void PrintIndex(StringStream* accumulator,
241 PrintMode mode,
242 int index);
243
244 // Get the top handler from the current stack iterator.
245 inline StackHandler* top_handler() const;
246
247 // Compute the stack frame type for the given state.
248 static Type ComputeType(State* state);
249
250 private:
251 const StackFrameIterator* iterator_;
252 State state_;
253
254 // Fill in the state of the calling frame.
255 virtual void ComputeCallerState(State* state) const = 0;
256
257 // Get the type and the state of the calling frame.
258 virtual Type GetCallerState(State* state) const;
259
Steve Blocka7e24c12009-10-30 11:49:00 +0000260 friend class StackFrameIterator;
261 friend class StackHandlerIterator;
262 friend class SafeStackFrameIterator;
263
Steve Block6ded16b2010-05-10 14:33:55 +0100264 private:
265 void operator=(const StackFrame& original);
Steve Blocka7e24c12009-10-30 11:49:00 +0000266};
267
268
269// Entry frames are used to enter JavaScript execution from C.
270class EntryFrame: public StackFrame {
271 public:
272 virtual Type type() const { return ENTRY; }
273
Iain Merrick75681382010-08-19 15:07:18 +0100274 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000275
276 // Garbage collection support.
277 virtual void Iterate(ObjectVisitor* v) const;
278
279 static EntryFrame* cast(StackFrame* frame) {
280 ASSERT(frame->is_entry());
281 return static_cast<EntryFrame*>(frame);
282 }
Steve Block6ded16b2010-05-10 14:33:55 +0100283 virtual void SetCallerFp(Address caller_fp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000284
285 protected:
286 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
287
288 // The caller stack pointer for entry frames is always zero. The
289 // real information about the caller frame is available through the
290 // link to the top exit frame.
291 virtual Address GetCallerStackPointer() const { return 0; }
292
293 private:
294 virtual void ComputeCallerState(State* state) const;
295 virtual Type GetCallerState(State* state) const;
296
297 friend class StackFrameIterator;
298};
299
300
301class EntryConstructFrame: public EntryFrame {
302 public:
303 virtual Type type() const { return ENTRY_CONSTRUCT; }
304
Iain Merrick75681382010-08-19 15:07:18 +0100305 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000306
307 static EntryConstructFrame* cast(StackFrame* frame) {
308 ASSERT(frame->is_entry_construct());
309 return static_cast<EntryConstructFrame*>(frame);
310 }
311
312 protected:
313 explicit EntryConstructFrame(StackFrameIterator* iterator)
314 : EntryFrame(iterator) { }
315
316 private:
317 friend class StackFrameIterator;
318};
319
320
321// Exit frames are used to exit JavaScript execution and go to C.
322class ExitFrame: public StackFrame {
323 public:
324 virtual Type type() const { return EXIT; }
325
Iain Merrick75681382010-08-19 15:07:18 +0100326 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000327
Steve Blockd0582a62009-12-15 09:54:21 +0000328 Object*& code_slot() const;
329
Steve Blocka7e24c12009-10-30 11:49:00 +0000330 // Garbage collection support.
331 virtual void Iterate(ObjectVisitor* v) const;
332
Steve Block6ded16b2010-05-10 14:33:55 +0100333 virtual void SetCallerFp(Address caller_fp);
334
Steve Blocka7e24c12009-10-30 11:49:00 +0000335 static ExitFrame* cast(StackFrame* frame) {
336 ASSERT(frame->is_exit());
337 return static_cast<ExitFrame*>(frame);
338 }
339
340 // Compute the state and type of an exit frame given a frame
341 // pointer. Used when constructing the first stack frame seen by an
342 // iterator and the frames following entry frames.
343 static Type GetStateForFramePointer(Address fp, State* state);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100344 static Address ComputeStackPointer(Address fp);
345 static void FillState(Address fp, Address sp, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000346
347 protected:
348 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
349
350 virtual Address GetCallerStackPointer() const;
351
352 private:
353 virtual void ComputeCallerState(State* state) const;
354
355 friend class StackFrameIterator;
356};
357
358
Steve Blocka7e24c12009-10-30 11:49:00 +0000359class StandardFrame: public StackFrame {
360 public:
361 // Testers.
362 virtual bool is_standard() const { return true; }
363
364 // Accessors.
365 inline Object* context() const;
366
367 // Access the expressions in the stack frame including locals.
368 inline Object* GetExpression(int index) const;
369 inline void SetExpression(int index, Object* value);
370 int ComputeExpressionsCount() const;
371
Steve Block6ded16b2010-05-10 14:33:55 +0100372 virtual void SetCallerFp(Address caller_fp);
373
Steve Blocka7e24c12009-10-30 11:49:00 +0000374 static StandardFrame* cast(StackFrame* frame) {
375 ASSERT(frame->is_standard());
376 return static_cast<StandardFrame*>(frame);
377 }
378
379 protected:
380 explicit StandardFrame(StackFrameIterator* iterator)
381 : StackFrame(iterator) { }
382
383 virtual void ComputeCallerState(State* state) const;
384
385 // Accessors.
386 inline Address caller_fp() const;
387 inline Address caller_pc() const;
388
389 // Computes the address of the PC field in the standard frame given
390 // by the provided frame pointer.
391 static inline Address ComputePCAddress(Address fp);
392
393 // Iterate over expression stack including stack handlers, locals,
394 // and parts of the fixed part including context and code fields.
395 void IterateExpressions(ObjectVisitor* v) const;
396
397 // Returns the address of the n'th expression stack element.
398 Address GetExpressionAddress(int n) const;
399
400 // Determines if the n'th expression stack element is in a stack
401 // handler or not. Requires traversing all handlers in this frame.
402 bool IsExpressionInsideHandler(int n) const;
403
404 // Determines if the standard frame for the given frame pointer is
405 // an arguments adaptor frame.
406 static inline bool IsArgumentsAdaptorFrame(Address fp);
407
408 // Determines if the standard frame for the given frame pointer is a
409 // construct frame.
410 static inline bool IsConstructFrame(Address fp);
411
412 private:
413 friend class StackFrame;
Kristian Monsen25f61362010-05-21 11:50:48 +0100414 friend class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000415};
416
417
Ben Murdochb0fe1622011-05-05 13:52:32 +0100418class FrameSummary BASE_EMBEDDED {
419 public:
420 FrameSummary(Object* receiver,
421 JSFunction* function,
422 Code* code,
423 int offset,
424 bool is_constructor)
425 : receiver_(receiver),
426 function_(function),
427 code_(code),
428 offset_(offset),
429 is_constructor_(is_constructor) { }
430 Handle<Object> receiver() { return receiver_; }
431 Handle<JSFunction> function() { return function_; }
432 Handle<Code> code() { return code_; }
433 Address pc() { return reinterpret_cast<Address>(*code_) + offset_; }
434 int offset() { return offset_; }
435 bool is_constructor() { return is_constructor_; }
436
437 void Print();
438
439 private:
440 Handle<Object> receiver_;
441 Handle<JSFunction> function_;
442 Handle<Code> code_;
443 int offset_;
444 bool is_constructor_;
445};
446
447
Steve Blocka7e24c12009-10-30 11:49:00 +0000448class JavaScriptFrame: public StandardFrame {
449 public:
450 virtual Type type() const { return JAVA_SCRIPT; }
451
452 // Accessors.
453 inline Object* function() const;
454 inline Object* receiver() const;
455 inline void set_receiver(Object* value);
456
457 // Access the parameters.
458 Object* GetParameter(int index) const;
459 int ComputeParametersCount() const;
460
Steve Blocka7e24c12009-10-30 11:49:00 +0000461 // Check if this frame is a constructor frame invoked through 'new'.
462 bool IsConstructor() const;
463
464 // Check if this frame has "adapted" arguments in the sense that the
465 // actual passed arguments are available in an arguments adaptor
466 // frame below it on the stack.
467 inline bool has_adapted_arguments() const;
468
469 // Garbage collection support.
470 virtual void Iterate(ObjectVisitor* v) const;
471
472 // Printing support.
473 virtual void Print(StringStream* accumulator,
474 PrintMode mode,
475 int index) const;
476
477 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100478 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000479
Ben Murdochb0fe1622011-05-05 13:52:32 +0100480 // Return a list with JSFunctions of this frame.
481 virtual void GetFunctions(List<JSFunction*>* functions);
482
483 // Build a list with summaries for this frame including all inlined frames.
484 virtual void Summarize(List<FrameSummary>* frames);
485
Steve Blocka7e24c12009-10-30 11:49:00 +0000486 static JavaScriptFrame* cast(StackFrame* frame) {
487 ASSERT(frame->is_java_script());
488 return static_cast<JavaScriptFrame*>(frame);
489 }
490
491 protected:
492 explicit JavaScriptFrame(StackFrameIterator* iterator)
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100493 : StandardFrame(iterator) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000494
495 virtual Address GetCallerStackPointer() const;
496
Ben Murdochb0fe1622011-05-05 13:52:32 +0100497 // Garbage collection support. Iterates over incoming arguments,
498 // receiver, and any callee-saved registers.
499 void IterateArguments(ObjectVisitor* v) const;
500
Steve Blocka7e24c12009-10-30 11:49:00 +0000501 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000502 inline Object* function_slot_object() const;
503
504 friend class StackFrameIterator;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100505 friend class StackTracer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000506};
507
508
Ben Murdochb0fe1622011-05-05 13:52:32 +0100509class OptimizedFrame : public JavaScriptFrame {
510 public:
511 virtual Type type() const { return OPTIMIZED; }
512
513 // GC support.
514 virtual void Iterate(ObjectVisitor* v) const;
515
516 // Return a list with JSFunctions of this frame.
517 // The functions are ordered bottom-to-top (i.e. functions.last()
518 // is the top-most activation)
519 virtual void GetFunctions(List<JSFunction*>* functions);
520
521 virtual void Summarize(List<FrameSummary>* frames);
522
523 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
524
525 protected:
526 explicit OptimizedFrame(StackFrameIterator* iterator)
527 : JavaScriptFrame(iterator) { }
528
529 private:
530 friend class StackFrameIterator;
531};
532
533
Steve Blocka7e24c12009-10-30 11:49:00 +0000534// Arguments adaptor frames are automatically inserted below
535// JavaScript frames when the actual number of parameters does not
536// match the formal number of parameters.
537class ArgumentsAdaptorFrame: public JavaScriptFrame {
538 public:
539 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
540
541 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100542 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000543
544 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
545 ASSERT(frame->is_arguments_adaptor());
546 return static_cast<ArgumentsAdaptorFrame*>(frame);
547 }
548
549 // Printing support.
550 virtual void Print(StringStream* accumulator,
551 PrintMode mode,
552 int index) const;
553 protected:
554 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
555 : JavaScriptFrame(iterator) { }
556
557 virtual Address GetCallerStackPointer() const;
558
559 private:
560 friend class StackFrameIterator;
561};
562
563
564class InternalFrame: public StandardFrame {
565 public:
566 virtual Type type() const { return INTERNAL; }
567
568 // Garbage collection support.
569 virtual void Iterate(ObjectVisitor* v) const;
570
571 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100572 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000573
574 static InternalFrame* cast(StackFrame* frame) {
575 ASSERT(frame->is_internal());
576 return static_cast<InternalFrame*>(frame);
577 }
578
579 protected:
580 explicit InternalFrame(StackFrameIterator* iterator)
581 : StandardFrame(iterator) { }
582
583 virtual Address GetCallerStackPointer() const;
584
585 private:
586 friend class StackFrameIterator;
587};
588
589
590// Construct frames are special trampoline frames introduced to handle
591// function invocations through 'new'.
592class ConstructFrame: public InternalFrame {
593 public:
594 virtual Type type() const { return CONSTRUCT; }
595
596 static ConstructFrame* cast(StackFrame* frame) {
597 ASSERT(frame->is_construct());
598 return static_cast<ConstructFrame*>(frame);
599 }
600
601 protected:
602 explicit ConstructFrame(StackFrameIterator* iterator)
603 : InternalFrame(iterator) { }
604
605 private:
606 friend class StackFrameIterator;
607};
608
609
610class StackFrameIterator BASE_EMBEDDED {
611 public:
612 // An iterator that iterates over the current thread's stack.
613 StackFrameIterator();
614
615 // An iterator that iterates over a given thread's stack.
616 explicit StackFrameIterator(ThreadLocalTop* thread);
617
618 // An iterator that can start from a given FP address.
619 // If use_top, then work as usual, if fp isn't NULL, use it,
620 // otherwise, do nothing.
Steve Block44f0eee2011-05-26 01:26:41 +0100621 StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000622
623 StackFrame* frame() const {
624 ASSERT(!done());
625 return frame_;
626 }
627
628 bool done() const { return frame_ == NULL; }
629 void Advance() { (this->*advance_)(); }
630
631 // Go back to the first frame.
632 void Reset();
633
634 private:
635#define DECLARE_SINGLETON(ignore, type) type type##_;
636 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
637#undef DECLARE_SINGLETON
638 StackFrame* frame_;
639 StackHandler* handler_;
640 ThreadLocalTop* thread_;
641 Address fp_;
642 Address sp_;
643 void (StackFrameIterator::*advance_)();
644
645 StackHandler* handler() const {
646 ASSERT(!done());
647 return handler_;
648 }
649
650 // Get the type-specific frame singleton in a given state.
651 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
652 // A helper function, can return a NULL pointer.
653 StackFrame* SingletonFor(StackFrame::Type type);
654
655 void AdvanceWithHandler();
656 void AdvanceWithoutHandler();
657
658 friend class StackFrame;
659 friend class SafeStackFrameIterator;
660 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
661};
662
663
664// Iterator that supports iterating through all JavaScript frames.
665template<typename Iterator>
666class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
667 public:
668 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
669
670 explicit JavaScriptFrameIteratorTemp(ThreadLocalTop* thread) :
671 iterator_(thread) {
672 if (!done()) Advance();
673 }
674
675 // Skip frames until the frame with the given id is reached.
676 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id);
677
678 JavaScriptFrameIteratorTemp(Address fp, Address sp,
679 Address low_bound, Address high_bound) :
680 iterator_(fp, sp, low_bound, high_bound) {
681 if (!done()) Advance();
682 }
683
Steve Block44f0eee2011-05-26 01:26:41 +0100684 JavaScriptFrameIteratorTemp(Isolate* isolate,
685 Address fp, Address sp,
686 Address low_bound, Address high_bound) :
687 iterator_(isolate, fp, sp, low_bound, high_bound) {
688 if (!done()) Advance();
689 }
690
Steve Blocka7e24c12009-10-30 11:49:00 +0000691 inline JavaScriptFrame* frame() const;
692
693 bool done() const { return iterator_.done(); }
694 void Advance();
695
696 // Advance to the frame holding the arguments for the current
697 // frame. This only affects the current frame if it has adapted
698 // arguments.
699 void AdvanceToArgumentsFrame();
700
701 // Go back to the first frame.
702 void Reset();
703
704 private:
705 Iterator iterator_;
706};
707
708
709typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
710
711
712// NOTE: The stack trace frame iterator is an iterator that only
713// traverse proper JavaScript frames; that is JavaScript frames that
714// have proper JavaScript functions. This excludes the problematic
715// functions in runtime.js.
716class StackTraceFrameIterator: public JavaScriptFrameIterator {
717 public:
718 StackTraceFrameIterator();
719 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000720
721 private:
722 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000723};
724
725
726class SafeStackFrameIterator BASE_EMBEDDED {
727 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100728 SafeStackFrameIterator(Isolate* isolate,
729 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000730 Address low_bound, Address high_bound);
731
732 StackFrame* frame() const {
733 ASSERT(is_working_iterator_);
734 return iterator_.frame();
735 }
736
737 bool done() const { return iteration_done_ ? true : iterator_.done(); }
738
739 void Advance();
740 void Reset();
741
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100742 static bool is_active() { return active_count_ > 0; }
743
Steve Blocka7e24c12009-10-30 11:49:00 +0000744 static bool IsWithinBounds(
745 Address low_bound, Address high_bound, Address addr) {
746 return low_bound <= addr && addr <= high_bound;
747 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000748
749 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100750 class StackAddressValidator {
751 public:
752 StackAddressValidator(Address low_bound, Address high_bound)
753 : low_bound_(low_bound), high_bound_(high_bound) { }
754 bool IsValid(Address addr) const {
755 return IsWithinBounds(low_bound_, high_bound_, addr);
756 }
757 private:
758 Address low_bound_;
759 Address high_bound_;
760 };
761
762 class ExitFrameValidator {
763 public:
764 explicit ExitFrameValidator(const StackAddressValidator& validator)
765 : validator_(validator) { }
766 ExitFrameValidator(Address low_bound, Address high_bound)
767 : validator_(low_bound, high_bound) { }
768 bool IsValidFP(Address fp);
769 private:
770 StackAddressValidator validator_;
771 };
772
Steve Blocka7e24c12009-10-30 11:49:00 +0000773 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100774 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000775 }
776 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
777 bool IsValidFrame(StackFrame* frame) const;
778 bool IsValidCaller(StackFrame* frame);
Steve Block44f0eee2011-05-26 01:26:41 +0100779 static bool IsValidTop(Isolate* isolate,
780 Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000781
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100782 // This is a nasty hack to make sure the active count is incremented
783 // before the constructor for the embedded iterator is invoked. This
784 // is needed because the constructor will start looking at frames
785 // right away and we need to make sure it doesn't start inspecting
786 // heap objects.
787 class ActiveCountMaintainer BASE_EMBEDDED {
788 public:
789 ActiveCountMaintainer() { active_count_++; }
790 ~ActiveCountMaintainer() { active_count_--; }
791 };
792
793 ActiveCountMaintainer maintainer_;
Steve Block44f0eee2011-05-26 01:26:41 +0100794 // TODO(isolates): this is dangerous.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100795 static int active_count_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100796 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000797 const bool is_valid_top_;
798 const bool is_valid_fp_;
799 const bool is_working_iterator_;
800 bool iteration_done_;
801 StackFrameIterator iterator_;
802};
803
804
805#ifdef ENABLE_LOGGING_AND_PROFILING
806typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
807 SafeJavaScriptFrameIterator;
808
809
810class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
811 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100812 explicit SafeStackTraceFrameIterator(Isolate* isolate,
813 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000814 Address low_bound, Address high_bound);
815 void Advance();
816};
817#endif
818
819
820class StackFrameLocator BASE_EMBEDDED {
821 public:
822 // Find the nth JavaScript frame on the stack. The caller must
823 // guarantee that such a frame exists.
824 JavaScriptFrame* FindJavaScriptFrame(int n);
825
826 private:
827 StackFrameIterator iterator_;
828};
829
830
Steve Block6ded16b2010-05-10 14:33:55 +0100831// Reads all frames on the current stack and copies them into the current
832// zone memory.
833Vector<StackFrame*> CreateStackMap();
834
Steve Blocka7e24c12009-10-30 11:49:00 +0000835} } // namespace v8::internal
836
837#endif // V8_FRAMES_H_