blob: 4f94ebc7d1d7d26cefbcd8c38cfde81493091f48 [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;
582 protected:
583 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
584 : JavaScriptFrame(iterator) { }
585
Ben Murdoch8b112d22011-06-08 16:22:53 +0100586 virtual int GetNumberOfIncomingArguments() const {
587 return Smi::cast(GetExpression(0))->value();
588 }
589
Steve Blocka7e24c12009-10-30 11:49:00 +0000590 virtual Address GetCallerStackPointer() const;
591
592 private:
593 friend class StackFrameIterator;
594};
595
596
597class InternalFrame: public StandardFrame {
598 public:
599 virtual Type type() const { return INTERNAL; }
600
601 // Garbage collection support.
602 virtual void Iterate(ObjectVisitor* v) const;
603
604 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100605 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000606
607 static InternalFrame* cast(StackFrame* frame) {
608 ASSERT(frame->is_internal());
609 return static_cast<InternalFrame*>(frame);
610 }
611
612 protected:
613 explicit InternalFrame(StackFrameIterator* iterator)
614 : StandardFrame(iterator) { }
615
616 virtual Address GetCallerStackPointer() const;
617
618 private:
619 friend class StackFrameIterator;
620};
621
622
623// Construct frames are special trampoline frames introduced to handle
624// function invocations through 'new'.
625class ConstructFrame: public InternalFrame {
626 public:
627 virtual Type type() const { return CONSTRUCT; }
628
629 static ConstructFrame* cast(StackFrame* frame) {
630 ASSERT(frame->is_construct());
631 return static_cast<ConstructFrame*>(frame);
632 }
633
634 protected:
635 explicit ConstructFrame(StackFrameIterator* iterator)
636 : InternalFrame(iterator) { }
637
638 private:
639 friend class StackFrameIterator;
640};
641
642
643class StackFrameIterator BASE_EMBEDDED {
644 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100645 // An iterator that iterates over the current thread's stack,
646 // and uses current isolate.
Steve Blocka7e24c12009-10-30 11:49:00 +0000647 StackFrameIterator();
648
Ben Murdoch8b112d22011-06-08 16:22:53 +0100649 // An iterator that iterates over the isolate's current thread's stack,
650 explicit StackFrameIterator(Isolate* isolate);
651
Steve Blocka7e24c12009-10-30 11:49:00 +0000652 // An iterator that iterates over a given thread's stack.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100653 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
Steve Blocka7e24c12009-10-30 11:49:00 +0000654
655 // An iterator that can start from a given FP address.
656 // If use_top, then work as usual, if fp isn't NULL, use it,
657 // otherwise, do nothing.
Steve Block44f0eee2011-05-26 01:26:41 +0100658 StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000659
660 StackFrame* frame() const {
661 ASSERT(!done());
662 return frame_;
663 }
664
Ben Murdoch8b112d22011-06-08 16:22:53 +0100665 Isolate* isolate() const { return isolate_; }
666
Steve Blocka7e24c12009-10-30 11:49:00 +0000667 bool done() const { return frame_ == NULL; }
668 void Advance() { (this->*advance_)(); }
669
670 // Go back to the first frame.
671 void Reset();
672
673 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100674 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000675#define DECLARE_SINGLETON(ignore, type) type type##_;
676 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
677#undef DECLARE_SINGLETON
678 StackFrame* frame_;
679 StackHandler* handler_;
680 ThreadLocalTop* thread_;
681 Address fp_;
682 Address sp_;
683 void (StackFrameIterator::*advance_)();
684
685 StackHandler* handler() const {
686 ASSERT(!done());
687 return handler_;
688 }
689
690 // Get the type-specific frame singleton in a given state.
691 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
692 // A helper function, can return a NULL pointer.
693 StackFrame* SingletonFor(StackFrame::Type type);
694
695 void AdvanceWithHandler();
696 void AdvanceWithoutHandler();
697
698 friend class StackFrame;
699 friend class SafeStackFrameIterator;
700 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
701};
702
703
704// Iterator that supports iterating through all JavaScript frames.
705template<typename Iterator>
706class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
707 public:
708 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
709
Ben Murdoch8b112d22011-06-08 16:22:53 +0100710 inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000711
712 // Skip frames until the frame with the given id is reached.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100713 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
714
715 inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
Steve Blocka7e24c12009-10-30 11:49:00 +0000716
717 JavaScriptFrameIteratorTemp(Address fp, Address sp,
718 Address low_bound, Address high_bound) :
719 iterator_(fp, sp, low_bound, high_bound) {
720 if (!done()) Advance();
721 }
722
Steve Block44f0eee2011-05-26 01:26:41 +0100723 JavaScriptFrameIteratorTemp(Isolate* isolate,
724 Address fp, Address sp,
725 Address low_bound, Address high_bound) :
726 iterator_(isolate, fp, sp, low_bound, high_bound) {
727 if (!done()) Advance();
728 }
729
Steve Blocka7e24c12009-10-30 11:49:00 +0000730 inline JavaScriptFrame* frame() const;
731
732 bool done() const { return iterator_.done(); }
733 void Advance();
734
735 // Advance to the frame holding the arguments for the current
736 // frame. This only affects the current frame if it has adapted
737 // arguments.
738 void AdvanceToArgumentsFrame();
739
740 // Go back to the first frame.
741 void Reset();
742
743 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100744 inline void AdvanceToId(StackFrame::Id id);
745
Steve Blocka7e24c12009-10-30 11:49:00 +0000746 Iterator iterator_;
747};
748
749
750typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
751
752
753// NOTE: The stack trace frame iterator is an iterator that only
754// traverse proper JavaScript frames; that is JavaScript frames that
755// have proper JavaScript functions. This excludes the problematic
756// functions in runtime.js.
757class StackTraceFrameIterator: public JavaScriptFrameIterator {
758 public:
759 StackTraceFrameIterator();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100760 explicit StackTraceFrameIterator(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000761 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000762
763 private:
764 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000765};
766
767
768class SafeStackFrameIterator BASE_EMBEDDED {
769 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100770 SafeStackFrameIterator(Isolate* isolate,
771 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000772 Address low_bound, Address high_bound);
773
774 StackFrame* frame() const {
775 ASSERT(is_working_iterator_);
776 return iterator_.frame();
777 }
778
779 bool done() const { return iteration_done_ ? true : iterator_.done(); }
780
781 void Advance();
782 void Reset();
783
Ben Murdoch8b112d22011-06-08 16:22:53 +0100784 static bool is_active(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100785
Steve Blocka7e24c12009-10-30 11:49:00 +0000786 static bool IsWithinBounds(
787 Address low_bound, Address high_bound, Address addr) {
788 return low_bound <= addr && addr <= high_bound;
789 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000790
791 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100792 class StackAddressValidator {
793 public:
794 StackAddressValidator(Address low_bound, Address high_bound)
795 : low_bound_(low_bound), high_bound_(high_bound) { }
796 bool IsValid(Address addr) const {
797 return IsWithinBounds(low_bound_, high_bound_, addr);
798 }
799 private:
800 Address low_bound_;
801 Address high_bound_;
802 };
803
804 class ExitFrameValidator {
805 public:
806 explicit ExitFrameValidator(const StackAddressValidator& validator)
807 : validator_(validator) { }
808 ExitFrameValidator(Address low_bound, Address high_bound)
809 : validator_(low_bound, high_bound) { }
810 bool IsValidFP(Address fp);
811 private:
812 StackAddressValidator validator_;
813 };
814
Steve Blocka7e24c12009-10-30 11:49:00 +0000815 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100816 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000817 }
818 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
819 bool IsValidFrame(StackFrame* frame) const;
820 bool IsValidCaller(StackFrame* frame);
Steve Block44f0eee2011-05-26 01:26:41 +0100821 static bool IsValidTop(Isolate* isolate,
822 Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000823
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100824 // This is a nasty hack to make sure the active count is incremented
825 // before the constructor for the embedded iterator is invoked. This
826 // is needed because the constructor will start looking at frames
827 // right away and we need to make sure it doesn't start inspecting
828 // heap objects.
829 class ActiveCountMaintainer BASE_EMBEDDED {
830 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100831 explicit ActiveCountMaintainer(Isolate* isolate);
832 ~ActiveCountMaintainer();
833 private:
834 Isolate* isolate_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100835 };
836
837 ActiveCountMaintainer maintainer_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100838 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000839 const bool is_valid_top_;
840 const bool is_valid_fp_;
841 const bool is_working_iterator_;
842 bool iteration_done_;
843 StackFrameIterator iterator_;
844};
845
846
Steve Blocka7e24c12009-10-30 11:49:00 +0000847typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
848 SafeJavaScriptFrameIterator;
849
850
851class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
852 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100853 explicit SafeStackTraceFrameIterator(Isolate* isolate,
854 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000855 Address low_bound, Address high_bound);
856 void Advance();
857};
Steve Blocka7e24c12009-10-30 11:49:00 +0000858
859
860class StackFrameLocator BASE_EMBEDDED {
861 public:
862 // Find the nth JavaScript frame on the stack. The caller must
863 // guarantee that such a frame exists.
864 JavaScriptFrame* FindJavaScriptFrame(int n);
865
866 private:
867 StackFrameIterator iterator_;
868};
869
870
Steve Block6ded16b2010-05-10 14:33:55 +0100871// Reads all frames on the current stack and copies them into the current
872// zone memory.
873Vector<StackFrame*> CreateStackMap();
874
Steve Blocka7e24c12009-10-30 11:49:00 +0000875} } // namespace v8::internal
876
877#endif // V8_FRAMES_H_