blob: fed11c4faf516f272b4f69e66c0278110bd90332 [file] [log] [blame]
Ben Murdoch69a99ed2011-11-30 16:03:39 +00001// Copyright 2011 the V8 project authors. All rights reserved.
Steve Blocka7e24c12009-10-30 11:49:00 +00002// 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
Ben Murdoch257744e2011-11-30 15:57:28 +000031#include "allocation.h"
Steve Block44f0eee2011-05-26 01:26:41 +010032#include "handles.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010033#include "safepoint-table.h"
34
Steve Blocka7e24c12009-10-30 11:49:00 +000035namespace v8 {
36namespace internal {
37
38typedef uint32_t RegList;
39
40// Get the number of registers in a given register list.
41int NumRegs(RegList list);
42
43// Return the code of the n-th saved register available to JavaScript.
44int JSCallerSavedCode(int n);
45
46
47// Forward declarations.
48class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +000049class ThreadLocalTop;
Steve Block44f0eee2011-05-26 01:26:41 +010050class Isolate;
Steve Blocka7e24c12009-10-30 11:49:00 +000051
Steve Block44f0eee2011-05-26 01:26:41 +010052class PcToCodeCache {
Kristian Monsen80d68ea2010-09-08 11:05:35 +010053 public:
54 struct PcToCodeCacheEntry {
55 Address pc;
56 Code* code;
Ben Murdochb8e0da22011-05-16 14:20:40 +010057 SafepointEntry safepoint_entry;
Kristian Monsen80d68ea2010-09-08 11:05:35 +010058 };
59
Steve Block44f0eee2011-05-26 01:26:41 +010060 explicit PcToCodeCache(Isolate* isolate) : isolate_(isolate) {
61 Flush();
Kristian Monsen80d68ea2010-09-08 11:05:35 +010062 }
63
Steve Block44f0eee2011-05-26 01:26:41 +010064 Code* GcSafeFindCodeForPc(Address pc);
65 Code* GcSafeCastToCode(HeapObject* object, Address pc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010066
Steve Block44f0eee2011-05-26 01:26:41 +010067 void Flush() {
Kristian Monsen80d68ea2010-09-08 11:05:35 +010068 memset(&cache_[0], 0, sizeof(cache_));
69 }
70
Steve Block44f0eee2011-05-26 01:26:41 +010071 PcToCodeCacheEntry* GetCacheEntry(Address pc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010072
73 private:
Steve Block44f0eee2011-05-26 01:26:41 +010074 PcToCodeCacheEntry* cache(int index) { return &cache_[index]; }
75
76 Isolate* isolate_;
77
Kristian Monsen0d5e1162010-09-30 15:31:59 +010078 static const int kPcToCodeCacheSize = 1024;
Steve Block44f0eee2011-05-26 01:26:41 +010079 PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
80
81 DISALLOW_COPY_AND_ASSIGN(PcToCodeCache);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010082};
83
84
Steve Blocka7e24c12009-10-30 11:49:00 +000085class StackHandler BASE_EMBEDDED {
86 public:
87 enum State {
88 ENTRY,
89 TRY_CATCH,
90 TRY_FINALLY
91 };
92
93 // Get the address of this stack handler.
94 inline Address address() const;
95
96 // Get the next stack handler in the chain.
97 inline StackHandler* next() const;
98
99 // Tells whether the given address is inside this handler.
100 inline bool includes(Address address) const;
101
102 // Garbage collection support.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100103 inline void Iterate(ObjectVisitor* v, Code* holder) const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000104
105 // Conversion support.
106 static inline StackHandler* FromAddress(Address address);
107
108 // Testers
109 bool is_entry() { return state() == ENTRY; }
110 bool is_try_catch() { return state() == TRY_CATCH; }
111 bool is_try_finally() { return state() == TRY_FINALLY; }
112
Steve Blocka7e24c12009-10-30 11:49:00 +0000113 private:
114 // Accessors.
115 inline State state() const;
116
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000117 inline Object** context_address() const;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100118 inline Address* pc_address() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000119
120 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
121};
122
123
124#define STACK_FRAME_TYPE_LIST(V) \
125 V(ENTRY, EntryFrame) \
126 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
127 V(EXIT, ExitFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000128 V(JAVA_SCRIPT, JavaScriptFrame) \
Ben Murdochb0fe1622011-05-05 13:52:32 +0100129 V(OPTIMIZED, OptimizedFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000130 V(INTERNAL, InternalFrame) \
131 V(CONSTRUCT, ConstructFrame) \
132 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
133
134
135// Abstract base class for all stack frames.
136class StackFrame BASE_EMBEDDED {
137 public:
138#define DECLARE_TYPE(type, ignore) type,
139 enum Type {
140 NONE = 0,
141 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
142 NUMBER_OF_TYPES
143 };
144#undef DECLARE_TYPE
145
146 // Opaque data type for identifying stack frames. Used extensively
147 // by the debugger.
Iain Merrick75681382010-08-19 15:07:18 +0100148 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
149 // has correct value range (see Issue 830 for more details).
150 enum Id {
151 ID_MIN_VALUE = kMinInt,
152 ID_MAX_VALUE = kMaxInt,
153 NO_ID = 0
154 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000155
Steve Block053d10c2011-06-13 19:13:29 +0100156 // Used to mark the outermost JS entry frame.
157 enum JsFrameMarker {
158 INNER_JSENTRY_FRAME = 0,
159 OUTERMOST_JSENTRY_FRAME = 1
160 };
161
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100162 struct State {
163 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
164 Address sp;
165 Address fp;
166 Address* pc_address;
167 };
168
Ben Murdoch8b112d22011-06-08 16:22:53 +0100169 // Copy constructor; it breaks the connection to host iterator
170 // (as an iterator usually lives on stack).
Steve Block6ded16b2010-05-10 14:33:55 +0100171 StackFrame(const StackFrame& original) {
172 this->state_ = original.state_;
173 this->iterator_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100174 this->isolate_ = original.isolate_;
Steve Block6ded16b2010-05-10 14:33:55 +0100175 }
176
Steve Blocka7e24c12009-10-30 11:49:00 +0000177 // Type testers.
178 bool is_entry() const { return type() == ENTRY; }
179 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
180 bool is_exit() const { return type() == EXIT; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100181 bool is_optimized() const { return type() == OPTIMIZED; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000182 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
183 bool is_internal() const { return type() == INTERNAL; }
184 bool is_construct() const { return type() == CONSTRUCT; }
185 virtual bool is_standard() const { return false; }
186
Ben Murdochb0fe1622011-05-05 13:52:32 +0100187 bool is_java_script() const {
188 Type type = this->type();
189 return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
190 }
191
Steve Blocka7e24c12009-10-30 11:49:00 +0000192 // Accessors.
193 Address sp() const { return state_.sp; }
194 Address fp() const { return state_.fp; }
195 Address caller_sp() const { return GetCallerStackPointer(); }
196
197 Address pc() const { return *pc_address(); }
198 void set_pc(Address pc) { *pc_address() = pc; }
199
Steve Block6ded16b2010-05-10 14:33:55 +0100200 virtual void SetCallerFp(Address caller_fp) = 0;
201
Steve Blocka7e24c12009-10-30 11:49:00 +0000202 Address* pc_address() const { return state_.pc_address; }
203
204 // Get the id of this stack frame.
205 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
206
207 // Checks if this frame includes any stack handlers.
208 bool HasHandler() const;
209
210 // Get the type of this frame.
211 virtual Type type() const = 0;
212
213 // Get the code associated with this frame.
Iain Merrick75681382010-08-19 15:07:18 +0100214 // This method could be called during marking phase of GC.
215 virtual Code* unchecked_code() const = 0;
216
217 // Get the code associated with this frame.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100218 Code* LookupCode() const {
219 return GetContainingCode(isolate(), pc());
Steve Block44f0eee2011-05-26 01:26:41 +0100220 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100221
222 // Get the code object that contains the given pc.
Steve Block44f0eee2011-05-26 01:26:41 +0100223 static inline Code* GetContainingCode(Isolate* isolate, Address pc);
Steve Blocka7e24c12009-10-30 11:49:00 +0000224
Ben Murdochb0fe1622011-05-05 13:52:32 +0100225 // Get the code object containing the given pc and fill in the
226 // safepoint entry and the number of stack slots. The pc must be at
227 // a safepoint.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100228 static Code* GetSafepointData(Isolate* isolate,
229 Address pc,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100230 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100231 unsigned* stack_slots);
232
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100233 virtual void Iterate(ObjectVisitor* v) const = 0;
234 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000235
Steve Blocka7e24c12009-10-30 11:49:00 +0000236
237 // Printing support.
238 enum PrintMode { OVERVIEW, DETAILS };
239 virtual void Print(StringStream* accumulator,
240 PrintMode mode,
241 int index) const { }
242
243 protected:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100244 inline explicit StackFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000245 virtual ~StackFrame() { }
246
Ben Murdoch8b112d22011-06-08 16:22:53 +0100247 Isolate* isolate() const { return isolate_; }
248
Steve Blocka7e24c12009-10-30 11:49:00 +0000249 // Compute the stack pointer for the calling frame.
250 virtual Address GetCallerStackPointer() const = 0;
251
252 // Printing support.
253 static void PrintIndex(StringStream* accumulator,
254 PrintMode mode,
255 int index);
256
257 // Get the top handler from the current stack iterator.
258 inline StackHandler* top_handler() const;
259
260 // Compute the stack frame type for the given state.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100261 static Type ComputeType(Isolate* isolate, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000262
263 private:
264 const StackFrameIterator* iterator_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100265 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000266 State state_;
267
268 // Fill in the state of the calling frame.
269 virtual void ComputeCallerState(State* state) const = 0;
270
271 // Get the type and the state of the calling frame.
272 virtual Type GetCallerState(State* state) const;
273
Ben Murdoch8b112d22011-06-08 16:22:53 +0100274 static const intptr_t kIsolateTag = 1;
275
Steve Blocka7e24c12009-10-30 11:49:00 +0000276 friend class StackFrameIterator;
277 friend class StackHandlerIterator;
278 friend class SafeStackFrameIterator;
279
Steve Block6ded16b2010-05-10 14:33:55 +0100280 private:
281 void operator=(const StackFrame& original);
Steve Blocka7e24c12009-10-30 11:49:00 +0000282};
283
284
285// Entry frames are used to enter JavaScript execution from C.
286class EntryFrame: public StackFrame {
287 public:
288 virtual Type type() const { return ENTRY; }
289
Iain Merrick75681382010-08-19 15:07:18 +0100290 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000291
292 // Garbage collection support.
293 virtual void Iterate(ObjectVisitor* v) const;
294
295 static EntryFrame* cast(StackFrame* frame) {
296 ASSERT(frame->is_entry());
297 return static_cast<EntryFrame*>(frame);
298 }
Steve Block6ded16b2010-05-10 14:33:55 +0100299 virtual void SetCallerFp(Address caller_fp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000300
301 protected:
302 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
303
304 // The caller stack pointer for entry frames is always zero. The
305 // real information about the caller frame is available through the
306 // link to the top exit frame.
307 virtual Address GetCallerStackPointer() const { return 0; }
308
309 private:
310 virtual void ComputeCallerState(State* state) const;
311 virtual Type GetCallerState(State* state) const;
312
313 friend class StackFrameIterator;
314};
315
316
317class EntryConstructFrame: public EntryFrame {
318 public:
319 virtual Type type() const { return ENTRY_CONSTRUCT; }
320
Iain Merrick75681382010-08-19 15:07:18 +0100321 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000322
323 static EntryConstructFrame* cast(StackFrame* frame) {
324 ASSERT(frame->is_entry_construct());
325 return static_cast<EntryConstructFrame*>(frame);
326 }
327
328 protected:
329 explicit EntryConstructFrame(StackFrameIterator* iterator)
330 : EntryFrame(iterator) { }
331
332 private:
333 friend class StackFrameIterator;
334};
335
336
337// Exit frames are used to exit JavaScript execution and go to C.
338class ExitFrame: public StackFrame {
339 public:
340 virtual Type type() const { return EXIT; }
341
Iain Merrick75681382010-08-19 15:07:18 +0100342 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000343
Steve Blockd0582a62009-12-15 09:54:21 +0000344 Object*& code_slot() const;
345
Steve Blocka7e24c12009-10-30 11:49:00 +0000346 // Garbage collection support.
347 virtual void Iterate(ObjectVisitor* v) const;
348
Steve Block6ded16b2010-05-10 14:33:55 +0100349 virtual void SetCallerFp(Address caller_fp);
350
Steve Blocka7e24c12009-10-30 11:49:00 +0000351 static ExitFrame* cast(StackFrame* frame) {
352 ASSERT(frame->is_exit());
353 return static_cast<ExitFrame*>(frame);
354 }
355
356 // Compute the state and type of an exit frame given a frame
357 // pointer. Used when constructing the first stack frame seen by an
358 // iterator and the frames following entry frames.
359 static Type GetStateForFramePointer(Address fp, State* state);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100360 static Address ComputeStackPointer(Address fp);
361 static void FillState(Address fp, Address sp, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000362
363 protected:
364 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
365
366 virtual Address GetCallerStackPointer() const;
367
368 private:
369 virtual void ComputeCallerState(State* state) const;
370
371 friend class StackFrameIterator;
372};
373
374
Steve Blocka7e24c12009-10-30 11:49:00 +0000375class StandardFrame: public StackFrame {
376 public:
377 // Testers.
378 virtual bool is_standard() const { return true; }
379
380 // Accessors.
381 inline Object* context() const;
382
383 // Access the expressions in the stack frame including locals.
384 inline Object* GetExpression(int index) const;
385 inline void SetExpression(int index, Object* value);
386 int ComputeExpressionsCount() const;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000387 static Object* GetExpression(Address fp, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000388
Steve Block6ded16b2010-05-10 14:33:55 +0100389 virtual void SetCallerFp(Address caller_fp);
390
Steve Blocka7e24c12009-10-30 11:49:00 +0000391 static StandardFrame* cast(StackFrame* frame) {
392 ASSERT(frame->is_standard());
393 return static_cast<StandardFrame*>(frame);
394 }
395
396 protected:
397 explicit StandardFrame(StackFrameIterator* iterator)
398 : StackFrame(iterator) { }
399
400 virtual void ComputeCallerState(State* state) const;
401
402 // Accessors.
403 inline Address caller_fp() const;
404 inline Address caller_pc() const;
405
406 // Computes the address of the PC field in the standard frame given
407 // by the provided frame pointer.
408 static inline Address ComputePCAddress(Address fp);
409
410 // Iterate over expression stack including stack handlers, locals,
411 // and parts of the fixed part including context and code fields.
412 void IterateExpressions(ObjectVisitor* v) const;
413
414 // Returns the address of the n'th expression stack element.
415 Address GetExpressionAddress(int n) const;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000416 static Address GetExpressionAddress(Address fp, int n);
Steve Blocka7e24c12009-10-30 11:49:00 +0000417
418 // Determines if the n'th expression stack element is in a stack
419 // handler or not. Requires traversing all handlers in this frame.
420 bool IsExpressionInsideHandler(int n) const;
421
422 // Determines if the standard frame for the given frame pointer is
423 // an arguments adaptor frame.
424 static inline bool IsArgumentsAdaptorFrame(Address fp);
425
426 // Determines if the standard frame for the given frame pointer is a
427 // construct frame.
428 static inline bool IsConstructFrame(Address fp);
429
430 private:
431 friend class StackFrame;
Kristian Monsen25f61362010-05-21 11:50:48 +0100432 friend class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000433};
434
435
Ben Murdochb0fe1622011-05-05 13:52:32 +0100436class FrameSummary BASE_EMBEDDED {
437 public:
438 FrameSummary(Object* receiver,
439 JSFunction* function,
440 Code* code,
441 int offset,
442 bool is_constructor)
443 : receiver_(receiver),
444 function_(function),
445 code_(code),
446 offset_(offset),
447 is_constructor_(is_constructor) { }
448 Handle<Object> receiver() { return receiver_; }
449 Handle<JSFunction> function() { return function_; }
450 Handle<Code> code() { return code_; }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100451 Address pc() { return code_->address() + offset_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100452 int offset() { return offset_; }
453 bool is_constructor() { return is_constructor_; }
454
455 void Print();
456
457 private:
458 Handle<Object> receiver_;
459 Handle<JSFunction> function_;
460 Handle<Code> code_;
461 int offset_;
462 bool is_constructor_;
463};
464
465
Steve Blocka7e24c12009-10-30 11:49:00 +0000466class JavaScriptFrame: public StandardFrame {
467 public:
468 virtual Type type() const { return JAVA_SCRIPT; }
469
470 // Accessors.
471 inline Object* function() const;
472 inline Object* receiver() const;
473 inline void set_receiver(Object* value);
474
475 // Access the parameters.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100476 inline Address GetParameterSlot(int index) const;
477 inline Object* GetParameter(int index) const;
478 inline int ComputeParametersCount() const {
479 return GetNumberOfIncomingArguments();
480 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000481
Steve Blocka7e24c12009-10-30 11:49:00 +0000482 // Check if this frame is a constructor frame invoked through 'new'.
483 bool IsConstructor() const;
484
485 // Check if this frame has "adapted" arguments in the sense that the
486 // actual passed arguments are available in an arguments adaptor
487 // frame below it on the stack.
488 inline bool has_adapted_arguments() const;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000489 int GetArgumentsLength() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000490
491 // Garbage collection support.
492 virtual void Iterate(ObjectVisitor* v) const;
493
494 // Printing support.
495 virtual void Print(StringStream* accumulator,
496 PrintMode mode,
497 int index) const;
498
499 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100500 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000501
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000502 // Returns the levels of inlining for this frame.
503 virtual int GetInlineCount() { return 1; }
504
Ben Murdochb0fe1622011-05-05 13:52:32 +0100505 // Return a list with JSFunctions of this frame.
506 virtual void GetFunctions(List<JSFunction*>* functions);
507
508 // Build a list with summaries for this frame including all inlined frames.
509 virtual void Summarize(List<FrameSummary>* frames);
510
Steve Blocka7e24c12009-10-30 11:49:00 +0000511 static JavaScriptFrame* cast(StackFrame* frame) {
512 ASSERT(frame->is_java_script());
513 return static_cast<JavaScriptFrame*>(frame);
514 }
515
516 protected:
517 explicit JavaScriptFrame(StackFrameIterator* iterator)
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100518 : StandardFrame(iterator) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000519
520 virtual Address GetCallerStackPointer() const;
521
Ben Murdoch8b112d22011-06-08 16:22:53 +0100522 virtual int GetNumberOfIncomingArguments() const;
523
Ben Murdochb0fe1622011-05-05 13:52:32 +0100524 // Garbage collection support. Iterates over incoming arguments,
525 // receiver, and any callee-saved registers.
526 void IterateArguments(ObjectVisitor* v) const;
527
Steve Blocka7e24c12009-10-30 11:49:00 +0000528 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000529 inline Object* function_slot_object() const;
530
531 friend class StackFrameIterator;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100532 friend class StackTracer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000533};
534
535
Ben Murdochb0fe1622011-05-05 13:52:32 +0100536class OptimizedFrame : public JavaScriptFrame {
537 public:
538 virtual Type type() const { return OPTIMIZED; }
539
540 // GC support.
541 virtual void Iterate(ObjectVisitor* v) const;
542
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000543 virtual int GetInlineCount();
544
Ben Murdochb0fe1622011-05-05 13:52:32 +0100545 // Return a list with JSFunctions of this frame.
546 // The functions are ordered bottom-to-top (i.e. functions.last()
547 // is the top-most activation)
548 virtual void GetFunctions(List<JSFunction*>* functions);
549
550 virtual void Summarize(List<FrameSummary>* frames);
551
552 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
553
554 protected:
555 explicit OptimizedFrame(StackFrameIterator* iterator)
556 : JavaScriptFrame(iterator) { }
557
558 private:
559 friend class StackFrameIterator;
560};
561
562
Steve Blocka7e24c12009-10-30 11:49:00 +0000563// Arguments adaptor frames are automatically inserted below
564// JavaScript frames when the actual number of parameters does not
565// match the formal number of parameters.
566class ArgumentsAdaptorFrame: public JavaScriptFrame {
567 public:
568 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
569
570 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100571 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000572
573 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
574 ASSERT(frame->is_arguments_adaptor());
575 return static_cast<ArgumentsAdaptorFrame*>(frame);
576 }
577
578 // Printing support.
579 virtual void Print(StringStream* accumulator,
580 PrintMode mode,
581 int index) const;
Ben Murdoch589d6972011-11-30 16:04:58 +0000582
Steve Blocka7e24c12009-10-30 11:49:00 +0000583 protected:
584 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
585 : JavaScriptFrame(iterator) { }
586
Ben Murdoch8b112d22011-06-08 16:22:53 +0100587 virtual int GetNumberOfIncomingArguments() const {
588 return Smi::cast(GetExpression(0))->value();
589 }
590
Steve Blocka7e24c12009-10-30 11:49:00 +0000591 virtual Address GetCallerStackPointer() const;
592
593 private:
594 friend class StackFrameIterator;
595};
596
597
598class InternalFrame: public StandardFrame {
599 public:
600 virtual Type type() const { return INTERNAL; }
601
602 // Garbage collection support.
603 virtual void Iterate(ObjectVisitor* v) const;
604
605 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100606 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000607
608 static InternalFrame* cast(StackFrame* frame) {
609 ASSERT(frame->is_internal());
610 return static_cast<InternalFrame*>(frame);
611 }
612
613 protected:
614 explicit InternalFrame(StackFrameIterator* iterator)
615 : StandardFrame(iterator) { }
616
617 virtual Address GetCallerStackPointer() const;
618
619 private:
620 friend class StackFrameIterator;
621};
622
623
624// Construct frames are special trampoline frames introduced to handle
625// function invocations through 'new'.
626class ConstructFrame: public InternalFrame {
627 public:
628 virtual Type type() const { return CONSTRUCT; }
629
630 static ConstructFrame* cast(StackFrame* frame) {
631 ASSERT(frame->is_construct());
632 return static_cast<ConstructFrame*>(frame);
633 }
634
635 protected:
636 explicit ConstructFrame(StackFrameIterator* iterator)
637 : InternalFrame(iterator) { }
638
639 private:
640 friend class StackFrameIterator;
641};
642
643
644class StackFrameIterator BASE_EMBEDDED {
645 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100646 // An iterator that iterates over the current thread's stack,
647 // and uses current isolate.
Steve Blocka7e24c12009-10-30 11:49:00 +0000648 StackFrameIterator();
649
Ben Murdoch8b112d22011-06-08 16:22:53 +0100650 // An iterator that iterates over the isolate's current thread's stack,
651 explicit StackFrameIterator(Isolate* isolate);
652
Steve Blocka7e24c12009-10-30 11:49:00 +0000653 // An iterator that iterates over a given thread's stack.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100654 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
Steve Blocka7e24c12009-10-30 11:49:00 +0000655
656 // An iterator that can start from a given FP address.
657 // If use_top, then work as usual, if fp isn't NULL, use it,
658 // otherwise, do nothing.
Steve Block44f0eee2011-05-26 01:26:41 +0100659 StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000660
661 StackFrame* frame() const {
662 ASSERT(!done());
663 return frame_;
664 }
665
Ben Murdoch8b112d22011-06-08 16:22:53 +0100666 Isolate* isolate() const { return isolate_; }
667
Steve Blocka7e24c12009-10-30 11:49:00 +0000668 bool done() const { return frame_ == NULL; }
669 void Advance() { (this->*advance_)(); }
670
671 // Go back to the first frame.
672 void Reset();
673
674 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100675 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000676#define DECLARE_SINGLETON(ignore, type) type type##_;
677 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
678#undef DECLARE_SINGLETON
679 StackFrame* frame_;
680 StackHandler* handler_;
681 ThreadLocalTop* thread_;
682 Address fp_;
683 Address sp_;
684 void (StackFrameIterator::*advance_)();
685
686 StackHandler* handler() const {
687 ASSERT(!done());
688 return handler_;
689 }
690
691 // Get the type-specific frame singleton in a given state.
692 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
693 // A helper function, can return a NULL pointer.
694 StackFrame* SingletonFor(StackFrame::Type type);
695
696 void AdvanceWithHandler();
697 void AdvanceWithoutHandler();
698
699 friend class StackFrame;
700 friend class SafeStackFrameIterator;
701 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
702};
703
704
705// Iterator that supports iterating through all JavaScript frames.
706template<typename Iterator>
707class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
708 public:
709 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
710
Ben Murdoch8b112d22011-06-08 16:22:53 +0100711 inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000712
713 // Skip frames until the frame with the given id is reached.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100714 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
715
716 inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
Steve Blocka7e24c12009-10-30 11:49:00 +0000717
718 JavaScriptFrameIteratorTemp(Address fp, Address sp,
719 Address low_bound, Address high_bound) :
720 iterator_(fp, sp, low_bound, high_bound) {
721 if (!done()) Advance();
722 }
723
Steve Block44f0eee2011-05-26 01:26:41 +0100724 JavaScriptFrameIteratorTemp(Isolate* isolate,
725 Address fp, Address sp,
726 Address low_bound, Address high_bound) :
727 iterator_(isolate, fp, sp, low_bound, high_bound) {
728 if (!done()) Advance();
729 }
730
Steve Blocka7e24c12009-10-30 11:49:00 +0000731 inline JavaScriptFrame* frame() const;
732
733 bool done() const { return iterator_.done(); }
734 void Advance();
735
736 // Advance to the frame holding the arguments for the current
737 // frame. This only affects the current frame if it has adapted
738 // arguments.
739 void AdvanceToArgumentsFrame();
740
741 // Go back to the first frame.
742 void Reset();
743
744 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100745 inline void AdvanceToId(StackFrame::Id id);
746
Steve Blocka7e24c12009-10-30 11:49:00 +0000747 Iterator iterator_;
748};
749
750
751typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
752
753
754// NOTE: The stack trace frame iterator is an iterator that only
755// traverse proper JavaScript frames; that is JavaScript frames that
756// have proper JavaScript functions. This excludes the problematic
757// functions in runtime.js.
758class StackTraceFrameIterator: public JavaScriptFrameIterator {
759 public:
760 StackTraceFrameIterator();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100761 explicit StackTraceFrameIterator(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000762 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000763
764 private:
765 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000766};
767
768
769class SafeStackFrameIterator BASE_EMBEDDED {
770 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100771 SafeStackFrameIterator(Isolate* isolate,
772 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000773 Address low_bound, Address high_bound);
774
775 StackFrame* frame() const {
776 ASSERT(is_working_iterator_);
777 return iterator_.frame();
778 }
779
780 bool done() const { return iteration_done_ ? true : iterator_.done(); }
781
782 void Advance();
783 void Reset();
784
Ben Murdoch8b112d22011-06-08 16:22:53 +0100785 static bool is_active(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100786
Steve Blocka7e24c12009-10-30 11:49:00 +0000787 static bool IsWithinBounds(
788 Address low_bound, Address high_bound, Address addr) {
789 return low_bound <= addr && addr <= high_bound;
790 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000791
792 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100793 class StackAddressValidator {
794 public:
795 StackAddressValidator(Address low_bound, Address high_bound)
796 : low_bound_(low_bound), high_bound_(high_bound) { }
797 bool IsValid(Address addr) const {
798 return IsWithinBounds(low_bound_, high_bound_, addr);
799 }
800 private:
801 Address low_bound_;
802 Address high_bound_;
803 };
804
805 class ExitFrameValidator {
806 public:
807 explicit ExitFrameValidator(const StackAddressValidator& validator)
808 : validator_(validator) { }
809 ExitFrameValidator(Address low_bound, Address high_bound)
810 : validator_(low_bound, high_bound) { }
811 bool IsValidFP(Address fp);
812 private:
813 StackAddressValidator validator_;
814 };
815
Steve Blocka7e24c12009-10-30 11:49:00 +0000816 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100817 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000818 }
819 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
820 bool IsValidFrame(StackFrame* frame) const;
821 bool IsValidCaller(StackFrame* frame);
Steve Block44f0eee2011-05-26 01:26:41 +0100822 static bool IsValidTop(Isolate* isolate,
823 Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000824
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100825 // This is a nasty hack to make sure the active count is incremented
826 // before the constructor for the embedded iterator is invoked. This
827 // is needed because the constructor will start looking at frames
828 // right away and we need to make sure it doesn't start inspecting
829 // heap objects.
830 class ActiveCountMaintainer BASE_EMBEDDED {
831 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100832 explicit ActiveCountMaintainer(Isolate* isolate);
833 ~ActiveCountMaintainer();
834 private:
835 Isolate* isolate_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100836 };
837
838 ActiveCountMaintainer maintainer_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100839 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000840 const bool is_valid_top_;
841 const bool is_valid_fp_;
842 const bool is_working_iterator_;
843 bool iteration_done_;
844 StackFrameIterator iterator_;
845};
846
847
Steve Blocka7e24c12009-10-30 11:49:00 +0000848typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
849 SafeJavaScriptFrameIterator;
850
851
852class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
853 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100854 explicit SafeStackTraceFrameIterator(Isolate* isolate,
855 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000856 Address low_bound, Address high_bound);
857 void Advance();
858};
Steve Blocka7e24c12009-10-30 11:49:00 +0000859
860
861class StackFrameLocator BASE_EMBEDDED {
862 public:
863 // Find the nth JavaScript frame on the stack. The caller must
864 // guarantee that such a frame exists.
865 JavaScriptFrame* FindJavaScriptFrame(int n);
866
867 private:
868 StackFrameIterator iterator_;
869};
870
871
Steve Block6ded16b2010-05-10 14:33:55 +0100872// Reads all frames on the current stack and copies them into the current
873// zone memory.
874Vector<StackFrame*> CreateStackMap();
875
Steve Blocka7e24c12009-10-30 11:49:00 +0000876} } // namespace v8::internal
877
878#endif // V8_FRAMES_H_