blob: 9071555197060e95c57cfbd434726b61a81f785a [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 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
Ben Murdoch3ef787d2012-04-12 10:51:47 +010052class InnerPointerToCodeCache {
Kristian Monsen80d68ea2010-09-08 11:05:35 +010053 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +010054 struct InnerPointerToCodeCacheEntry {
55 Address inner_pointer;
Kristian Monsen80d68ea2010-09-08 11:05:35 +010056 Code* code;
Ben Murdochb8e0da22011-05-16 14:20:40 +010057 SafepointEntry safepoint_entry;
Kristian Monsen80d68ea2010-09-08 11:05:35 +010058 };
59
Ben Murdoch3ef787d2012-04-12 10:51:47 +010060 explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) {
Steve Block44f0eee2011-05-26 01:26:41 +010061 Flush();
Kristian Monsen80d68ea2010-09-08 11:05:35 +010062 }
63
Ben Murdoch3ef787d2012-04-12 10:51:47 +010064 Code* GcSafeFindCodeForInnerPointer(Address inner_pointer);
65 Code* GcSafeCastToCode(HeapObject* object, Address inner_pointer);
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
Ben Murdoch3ef787d2012-04-12 10:51:47 +010071 InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010072
73 private:
Ben Murdoch3ef787d2012-04-12 10:51:47 +010074 InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; }
Steve Block44f0eee2011-05-26 01:26:41 +010075
76 Isolate* isolate_;
77
Ben Murdoch3ef787d2012-04-12 10:51:47 +010078 static const int kInnerPointerToCodeCacheSize = 1024;
79 InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize];
Steve Block44f0eee2011-05-26 01:26:41 +010080
Ben Murdoch3ef787d2012-04-12 10:51:47 +010081 DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010082};
83
84
Steve Blocka7e24c12009-10-30 11:49:00 +000085class StackHandler BASE_EMBEDDED {
86 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +010087 enum Kind {
88 JS_ENTRY,
89 CATCH,
90 FINALLY,
91 LAST_KIND = FINALLY
Steve Blocka7e24c12009-10-30 11:49:00 +000092 };
93
Ben Murdoch3ef787d2012-04-12 10:51:47 +010094 static const int kKindWidth = 2;
95 STATIC_ASSERT(LAST_KIND < (1 << kKindWidth));
96 static const int kIndexWidth = 32 - kKindWidth;
97 class KindField: public BitField<StackHandler::Kind, 0, kKindWidth> {};
98 class IndexField: public BitField<unsigned, kKindWidth, kIndexWidth> {};
99
Steve Blocka7e24c12009-10-30 11:49:00 +0000100 // Get the address of this stack handler.
101 inline Address address() const;
102
103 // Get the next stack handler in the chain.
104 inline StackHandler* next() const;
105
106 // Tells whether the given address is inside this handler.
107 inline bool includes(Address address) const;
108
109 // Garbage collection support.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100110 inline void Iterate(ObjectVisitor* v, Code* holder) const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000111
112 // Conversion support.
113 static inline StackHandler* FromAddress(Address address);
114
115 // Testers
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100116 inline bool is_js_entry() const;
117 inline bool is_catch() const;
118 inline bool is_finally() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000119
Steve Blocka7e24c12009-10-30 11:49:00 +0000120 private:
121 // Accessors.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100122 inline Kind kind() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000123
Ben Murdoch69a99ed2011-11-30 16:03:39 +0000124 inline Object** context_address() const;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100125 inline Object** code_address() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000126
127 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
128};
129
130
131#define STACK_FRAME_TYPE_LIST(V) \
132 V(ENTRY, EntryFrame) \
133 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
134 V(EXIT, ExitFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000135 V(JAVA_SCRIPT, JavaScriptFrame) \
Ben Murdochb0fe1622011-05-05 13:52:32 +0100136 V(OPTIMIZED, OptimizedFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 V(INTERNAL, InternalFrame) \
138 V(CONSTRUCT, ConstructFrame) \
139 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
140
141
142// Abstract base class for all stack frames.
143class StackFrame BASE_EMBEDDED {
144 public:
145#define DECLARE_TYPE(type, ignore) type,
146 enum Type {
147 NONE = 0,
148 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100149 NUMBER_OF_TYPES,
150 // Used by FrameScope to indicate that the stack frame is constructed
151 // manually and the FrameScope does not need to emit code.
152 MANUAL
Steve Blocka7e24c12009-10-30 11:49:00 +0000153 };
154#undef DECLARE_TYPE
155
156 // Opaque data type for identifying stack frames. Used extensively
157 // by the debugger.
Iain Merrick75681382010-08-19 15:07:18 +0100158 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
159 // has correct value range (see Issue 830 for more details).
160 enum Id {
161 ID_MIN_VALUE = kMinInt,
162 ID_MAX_VALUE = kMaxInt,
163 NO_ID = 0
164 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000165
Steve Block053d10c2011-06-13 19:13:29 +0100166 // Used to mark the outermost JS entry frame.
167 enum JsFrameMarker {
168 INNER_JSENTRY_FRAME = 0,
169 OUTERMOST_JSENTRY_FRAME = 1
170 };
171
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100172 struct State {
173 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
174 Address sp;
175 Address fp;
176 Address* pc_address;
177 };
178
Ben Murdoch8b112d22011-06-08 16:22:53 +0100179 // Copy constructor; it breaks the connection to host iterator
180 // (as an iterator usually lives on stack).
Steve Block6ded16b2010-05-10 14:33:55 +0100181 StackFrame(const StackFrame& original) {
182 this->state_ = original.state_;
183 this->iterator_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100184 this->isolate_ = original.isolate_;
Steve Block6ded16b2010-05-10 14:33:55 +0100185 }
186
Steve Blocka7e24c12009-10-30 11:49:00 +0000187 // Type testers.
188 bool is_entry() const { return type() == ENTRY; }
189 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
190 bool is_exit() const { return type() == EXIT; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100191 bool is_optimized() const { return type() == OPTIMIZED; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000192 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
193 bool is_internal() const { return type() == INTERNAL; }
194 bool is_construct() const { return type() == CONSTRUCT; }
195 virtual bool is_standard() const { return false; }
196
Ben Murdochb0fe1622011-05-05 13:52:32 +0100197 bool is_java_script() const {
198 Type type = this->type();
199 return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
200 }
201
Steve Blocka7e24c12009-10-30 11:49:00 +0000202 // Accessors.
203 Address sp() const { return state_.sp; }
204 Address fp() const { return state_.fp; }
205 Address caller_sp() const { return GetCallerStackPointer(); }
206
207 Address pc() const { return *pc_address(); }
208 void set_pc(Address pc) { *pc_address() = pc; }
209
Steve Block6ded16b2010-05-10 14:33:55 +0100210 virtual void SetCallerFp(Address caller_fp) = 0;
211
Steve Blocka7e24c12009-10-30 11:49:00 +0000212 Address* pc_address() const { return state_.pc_address; }
213
214 // Get the id of this stack frame.
215 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
216
217 // Checks if this frame includes any stack handlers.
218 bool HasHandler() const;
219
220 // Get the type of this frame.
221 virtual Type type() const = 0;
222
223 // Get the code associated with this frame.
Iain Merrick75681382010-08-19 15:07:18 +0100224 // This method could be called during marking phase of GC.
225 virtual Code* unchecked_code() const = 0;
226
227 // Get the code associated with this frame.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100228 inline Code* LookupCode() const;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100229
230 // Get the code object that contains the given pc.
Steve Block44f0eee2011-05-26 01:26:41 +0100231 static inline Code* GetContainingCode(Isolate* isolate, Address pc);
Steve Blocka7e24c12009-10-30 11:49:00 +0000232
Ben Murdochb0fe1622011-05-05 13:52:32 +0100233 // Get the code object containing the given pc and fill in the
234 // safepoint entry and the number of stack slots. The pc must be at
235 // a safepoint.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100236 static Code* GetSafepointData(Isolate* isolate,
237 Address pc,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100238 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100239 unsigned* stack_slots);
240
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100241 virtual void Iterate(ObjectVisitor* v) const = 0;
242 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000243
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100244 // Sets a callback function for return-address rewriting profilers
245 // to resolve the location of a return address to the location of the
246 // profiler's stashed return address.
247 static void SetReturnAddressLocationResolver(
248 ReturnAddressLocationResolver resolver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000249
250 // Printing support.
251 enum PrintMode { OVERVIEW, DETAILS };
252 virtual void Print(StringStream* accumulator,
253 PrintMode mode,
254 int index) const { }
255
256 protected:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100257 inline explicit StackFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000258 virtual ~StackFrame() { }
259
Ben Murdoch8b112d22011-06-08 16:22:53 +0100260 Isolate* isolate() const { return isolate_; }
261
Steve Blocka7e24c12009-10-30 11:49:00 +0000262 // Compute the stack pointer for the calling frame.
263 virtual Address GetCallerStackPointer() const = 0;
264
265 // Printing support.
266 static void PrintIndex(StringStream* accumulator,
267 PrintMode mode,
268 int index);
269
270 // Get the top handler from the current stack iterator.
271 inline StackHandler* top_handler() const;
272
273 // Compute the stack frame type for the given state.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100274 static Type ComputeType(Isolate* isolate, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000275
276 private:
277 const StackFrameIterator* iterator_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100278 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000279 State state_;
280
281 // Fill in the state of the calling frame.
282 virtual void ComputeCallerState(State* state) const = 0;
283
284 // Get the type and the state of the calling frame.
285 virtual Type GetCallerState(State* state) const;
286
Ben Murdoch8b112d22011-06-08 16:22:53 +0100287 static const intptr_t kIsolateTag = 1;
288
Steve Blocka7e24c12009-10-30 11:49:00 +0000289 friend class StackFrameIterator;
290 friend class StackHandlerIterator;
291 friend class SafeStackFrameIterator;
292
Steve Block6ded16b2010-05-10 14:33:55 +0100293 private:
294 void operator=(const StackFrame& original);
Steve Blocka7e24c12009-10-30 11:49:00 +0000295};
296
297
298// Entry frames are used to enter JavaScript execution from C.
299class EntryFrame: public StackFrame {
300 public:
301 virtual Type type() const { return ENTRY; }
302
Iain Merrick75681382010-08-19 15:07:18 +0100303 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000304
305 // Garbage collection support.
306 virtual void Iterate(ObjectVisitor* v) const;
307
308 static EntryFrame* cast(StackFrame* frame) {
309 ASSERT(frame->is_entry());
310 return static_cast<EntryFrame*>(frame);
311 }
Steve Block6ded16b2010-05-10 14:33:55 +0100312 virtual void SetCallerFp(Address caller_fp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000313
314 protected:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100315 inline explicit EntryFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000316
317 // The caller stack pointer for entry frames is always zero. The
318 // real information about the caller frame is available through the
319 // link to the top exit frame.
320 virtual Address GetCallerStackPointer() const { return 0; }
321
322 private:
323 virtual void ComputeCallerState(State* state) const;
324 virtual Type GetCallerState(State* state) const;
325
326 friend class StackFrameIterator;
327};
328
329
330class EntryConstructFrame: public EntryFrame {
331 public:
332 virtual Type type() const { return ENTRY_CONSTRUCT; }
333
Iain Merrick75681382010-08-19 15:07:18 +0100334 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000335
336 static EntryConstructFrame* cast(StackFrame* frame) {
337 ASSERT(frame->is_entry_construct());
338 return static_cast<EntryConstructFrame*>(frame);
339 }
340
341 protected:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100342 inline explicit EntryConstructFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000343
344 private:
345 friend class StackFrameIterator;
346};
347
348
349// Exit frames are used to exit JavaScript execution and go to C.
350class ExitFrame: public StackFrame {
351 public:
352 virtual Type type() const { return EXIT; }
353
Iain Merrick75681382010-08-19 15:07:18 +0100354 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000355
Steve Blockd0582a62009-12-15 09:54:21 +0000356 Object*& code_slot() const;
357
Steve Blocka7e24c12009-10-30 11:49:00 +0000358 // Garbage collection support.
359 virtual void Iterate(ObjectVisitor* v) const;
360
Steve Block6ded16b2010-05-10 14:33:55 +0100361 virtual void SetCallerFp(Address caller_fp);
362
Steve Blocka7e24c12009-10-30 11:49:00 +0000363 static ExitFrame* cast(StackFrame* frame) {
364 ASSERT(frame->is_exit());
365 return static_cast<ExitFrame*>(frame);
366 }
367
368 // Compute the state and type of an exit frame given a frame
369 // pointer. Used when constructing the first stack frame seen by an
370 // iterator and the frames following entry frames.
371 static Type GetStateForFramePointer(Address fp, State* state);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100372 static Address ComputeStackPointer(Address fp);
373 static void FillState(Address fp, Address sp, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000374
375 protected:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100376 inline explicit ExitFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000377
378 virtual Address GetCallerStackPointer() const;
379
380 private:
381 virtual void ComputeCallerState(State* state) const;
382
383 friend class StackFrameIterator;
384};
385
386
Steve Blocka7e24c12009-10-30 11:49:00 +0000387class StandardFrame: public StackFrame {
388 public:
389 // Testers.
390 virtual bool is_standard() const { return true; }
391
392 // Accessors.
393 inline Object* context() const;
394
395 // Access the expressions in the stack frame including locals.
396 inline Object* GetExpression(int index) const;
397 inline void SetExpression(int index, Object* value);
398 int ComputeExpressionsCount() const;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000399 static Object* GetExpression(Address fp, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000400
Steve Block6ded16b2010-05-10 14:33:55 +0100401 virtual void SetCallerFp(Address caller_fp);
402
Steve Blocka7e24c12009-10-30 11:49:00 +0000403 static StandardFrame* cast(StackFrame* frame) {
404 ASSERT(frame->is_standard());
405 return static_cast<StandardFrame*>(frame);
406 }
407
408 protected:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100409 inline explicit StandardFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000410
411 virtual void ComputeCallerState(State* state) const;
412
413 // Accessors.
414 inline Address caller_fp() const;
415 inline Address caller_pc() const;
416
417 // Computes the address of the PC field in the standard frame given
418 // by the provided frame pointer.
419 static inline Address ComputePCAddress(Address fp);
420
421 // Iterate over expression stack including stack handlers, locals,
422 // and parts of the fixed part including context and code fields.
423 void IterateExpressions(ObjectVisitor* v) const;
424
425 // Returns the address of the n'th expression stack element.
426 Address GetExpressionAddress(int n) const;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000427 static Address GetExpressionAddress(Address fp, int n);
Steve Blocka7e24c12009-10-30 11:49:00 +0000428
429 // Determines if the n'th expression stack element is in a stack
430 // handler or not. Requires traversing all handlers in this frame.
431 bool IsExpressionInsideHandler(int n) const;
432
433 // Determines if the standard frame for the given frame pointer is
434 // an arguments adaptor frame.
435 static inline bool IsArgumentsAdaptorFrame(Address fp);
436
437 // Determines if the standard frame for the given frame pointer is a
438 // construct frame.
439 static inline bool IsConstructFrame(Address fp);
440
441 private:
442 friend class StackFrame;
Kristian Monsen25f61362010-05-21 11:50:48 +0100443 friend class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000444};
445
446
Ben Murdochb0fe1622011-05-05 13:52:32 +0100447class FrameSummary BASE_EMBEDDED {
448 public:
449 FrameSummary(Object* receiver,
450 JSFunction* function,
451 Code* code,
452 int offset,
453 bool is_constructor)
454 : receiver_(receiver),
455 function_(function),
456 code_(code),
457 offset_(offset),
458 is_constructor_(is_constructor) { }
459 Handle<Object> receiver() { return receiver_; }
460 Handle<JSFunction> function() { return function_; }
461 Handle<Code> code() { return code_; }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100462 Address pc() { return code_->address() + offset_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100463 int offset() { return offset_; }
464 bool is_constructor() { return is_constructor_; }
465
466 void Print();
467
468 private:
469 Handle<Object> receiver_;
470 Handle<JSFunction> function_;
471 Handle<Code> code_;
472 int offset_;
473 bool is_constructor_;
474};
475
476
Steve Blocka7e24c12009-10-30 11:49:00 +0000477class JavaScriptFrame: public StandardFrame {
478 public:
479 virtual Type type() const { return JAVA_SCRIPT; }
480
481 // Accessors.
482 inline Object* function() const;
483 inline Object* receiver() const;
484 inline void set_receiver(Object* value);
485
486 // Access the parameters.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100487 inline Address GetParameterSlot(int index) const;
488 inline Object* GetParameter(int index) const;
489 inline int ComputeParametersCount() const {
490 return GetNumberOfIncomingArguments();
491 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000492
Steve Blocka7e24c12009-10-30 11:49:00 +0000493 // Check if this frame is a constructor frame invoked through 'new'.
494 bool IsConstructor() const;
495
496 // Check if this frame has "adapted" arguments in the sense that the
497 // actual passed arguments are available in an arguments adaptor
498 // frame below it on the stack.
499 inline bool has_adapted_arguments() const;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000500 int GetArgumentsLength() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000501
502 // Garbage collection support.
503 virtual void Iterate(ObjectVisitor* v) const;
504
505 // Printing support.
506 virtual void Print(StringStream* accumulator,
507 PrintMode mode,
508 int index) const;
509
510 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100511 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000512
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000513 // Returns the levels of inlining for this frame.
514 virtual int GetInlineCount() { return 1; }
515
Ben Murdochb0fe1622011-05-05 13:52:32 +0100516 // Return a list with JSFunctions of this frame.
517 virtual void GetFunctions(List<JSFunction*>* functions);
518
519 // Build a list with summaries for this frame including all inlined frames.
520 virtual void Summarize(List<FrameSummary>* frames);
521
Steve Blocka7e24c12009-10-30 11:49:00 +0000522 static JavaScriptFrame* cast(StackFrame* frame) {
523 ASSERT(frame->is_java_script());
524 return static_cast<JavaScriptFrame*>(frame);
525 }
526
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100527 static void PrintTop(FILE* file, bool print_args, bool print_line_number);
528
Steve Blocka7e24c12009-10-30 11:49:00 +0000529 protected:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100530 inline explicit JavaScriptFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000531
532 virtual Address GetCallerStackPointer() const;
533
Ben Murdoch8b112d22011-06-08 16:22:53 +0100534 virtual int GetNumberOfIncomingArguments() const;
535
Ben Murdochb0fe1622011-05-05 13:52:32 +0100536 // Garbage collection support. Iterates over incoming arguments,
537 // receiver, and any callee-saved registers.
538 void IterateArguments(ObjectVisitor* v) const;
539
Steve Blocka7e24c12009-10-30 11:49:00 +0000540 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000541 inline Object* function_slot_object() const;
542
543 friend class StackFrameIterator;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100544 friend class StackTracer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000545};
546
547
Ben Murdochb0fe1622011-05-05 13:52:32 +0100548class OptimizedFrame : public JavaScriptFrame {
549 public:
550 virtual Type type() const { return OPTIMIZED; }
551
552 // GC support.
553 virtual void Iterate(ObjectVisitor* v) const;
554
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000555 virtual int GetInlineCount();
556
Ben Murdochb0fe1622011-05-05 13:52:32 +0100557 // Return a list with JSFunctions of this frame.
558 // The functions are ordered bottom-to-top (i.e. functions.last()
559 // is the top-most activation)
560 virtual void GetFunctions(List<JSFunction*>* functions);
561
562 virtual void Summarize(List<FrameSummary>* frames);
563
564 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
565
566 protected:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100567 inline explicit OptimizedFrame(StackFrameIterator* iterator);
Ben Murdochb0fe1622011-05-05 13:52:32 +0100568
569 private:
570 friend class StackFrameIterator;
571};
572
573
Steve Blocka7e24c12009-10-30 11:49:00 +0000574// Arguments adaptor frames are automatically inserted below
575// JavaScript frames when the actual number of parameters does not
576// match the formal number of parameters.
577class ArgumentsAdaptorFrame: public JavaScriptFrame {
578 public:
579 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
580
581 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100582 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000583
584 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
585 ASSERT(frame->is_arguments_adaptor());
586 return static_cast<ArgumentsAdaptorFrame*>(frame);
587 }
588
589 // Printing support.
590 virtual void Print(StringStream* accumulator,
591 PrintMode mode,
592 int index) const;
Ben Murdoch589d6972011-11-30 16:04:58 +0000593
Steve Blocka7e24c12009-10-30 11:49:00 +0000594 protected:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100595 inline explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000596
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100597 virtual int GetNumberOfIncomingArguments() const;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100598
Steve Blocka7e24c12009-10-30 11:49:00 +0000599 virtual Address GetCallerStackPointer() const;
600
601 private:
602 friend class StackFrameIterator;
603};
604
605
606class InternalFrame: public StandardFrame {
607 public:
608 virtual Type type() const { return INTERNAL; }
609
610 // Garbage collection support.
611 virtual void Iterate(ObjectVisitor* v) const;
612
613 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100614 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000615
616 static InternalFrame* cast(StackFrame* frame) {
617 ASSERT(frame->is_internal());
618 return static_cast<InternalFrame*>(frame);
619 }
620
621 protected:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100622 inline explicit InternalFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000623
624 virtual Address GetCallerStackPointer() const;
625
626 private:
627 friend class StackFrameIterator;
628};
629
630
631// Construct frames are special trampoline frames introduced to handle
632// function invocations through 'new'.
633class ConstructFrame: public InternalFrame {
634 public:
635 virtual Type type() const { return CONSTRUCT; }
636
637 static ConstructFrame* cast(StackFrame* frame) {
638 ASSERT(frame->is_construct());
639 return static_cast<ConstructFrame*>(frame);
640 }
641
642 protected:
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100643 inline explicit ConstructFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000644
645 private:
646 friend class StackFrameIterator;
647};
648
649
650class StackFrameIterator BASE_EMBEDDED {
651 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100652 // An iterator that iterates over the current thread's stack,
653 // and uses current isolate.
Steve Blocka7e24c12009-10-30 11:49:00 +0000654 StackFrameIterator();
655
Ben Murdoch8b112d22011-06-08 16:22:53 +0100656 // An iterator that iterates over the isolate's current thread's stack,
657 explicit StackFrameIterator(Isolate* isolate);
658
Steve Blocka7e24c12009-10-30 11:49:00 +0000659 // An iterator that iterates over a given thread's stack.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100660 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
Steve Blocka7e24c12009-10-30 11:49:00 +0000661
662 // An iterator that can start from a given FP address.
663 // If use_top, then work as usual, if fp isn't NULL, use it,
664 // otherwise, do nothing.
Steve Block44f0eee2011-05-26 01:26:41 +0100665 StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000666
667 StackFrame* frame() const {
668 ASSERT(!done());
669 return frame_;
670 }
671
Ben Murdoch8b112d22011-06-08 16:22:53 +0100672 Isolate* isolate() const { return isolate_; }
673
Steve Blocka7e24c12009-10-30 11:49:00 +0000674 bool done() const { return frame_ == NULL; }
675 void Advance() { (this->*advance_)(); }
676
677 // Go back to the first frame.
678 void Reset();
679
680 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100681 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000682#define DECLARE_SINGLETON(ignore, type) type type##_;
683 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
684#undef DECLARE_SINGLETON
685 StackFrame* frame_;
686 StackHandler* handler_;
687 ThreadLocalTop* thread_;
688 Address fp_;
689 Address sp_;
690 void (StackFrameIterator::*advance_)();
691
692 StackHandler* handler() const {
693 ASSERT(!done());
694 return handler_;
695 }
696
697 // Get the type-specific frame singleton in a given state.
698 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
699 // A helper function, can return a NULL pointer.
700 StackFrame* SingletonFor(StackFrame::Type type);
701
702 void AdvanceWithHandler();
703 void AdvanceWithoutHandler();
704
705 friend class StackFrame;
706 friend class SafeStackFrameIterator;
707 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
708};
709
710
711// Iterator that supports iterating through all JavaScript frames.
712template<typename Iterator>
713class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
714 public:
715 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
716
Ben Murdoch8b112d22011-06-08 16:22:53 +0100717 inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000718
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100719 inline JavaScriptFrameIteratorTemp(Isolate* isolate, ThreadLocalTop* top);
720
Steve Blocka7e24c12009-10-30 11:49:00 +0000721 // Skip frames until the frame with the given id is reached.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100722 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
723
724 inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
Steve Blocka7e24c12009-10-30 11:49:00 +0000725
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100726 JavaScriptFrameIteratorTemp(Address fp,
727 Address sp,
728 Address low_bound,
729 Address high_bound) :
Steve Blocka7e24c12009-10-30 11:49:00 +0000730 iterator_(fp, sp, low_bound, high_bound) {
731 if (!done()) Advance();
732 }
733
Steve Block44f0eee2011-05-26 01:26:41 +0100734 JavaScriptFrameIteratorTemp(Isolate* isolate,
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100735 Address fp,
736 Address sp,
737 Address low_bound,
738 Address high_bound) :
Steve Block44f0eee2011-05-26 01:26:41 +0100739 iterator_(isolate, fp, sp, low_bound, high_bound) {
740 if (!done()) Advance();
741 }
742
Steve Blocka7e24c12009-10-30 11:49:00 +0000743 inline JavaScriptFrame* frame() const;
744
745 bool done() const { return iterator_.done(); }
746 void Advance();
747
748 // Advance to the frame holding the arguments for the current
749 // frame. This only affects the current frame if it has adapted
750 // arguments.
751 void AdvanceToArgumentsFrame();
752
753 // Go back to the first frame.
754 void Reset();
755
756 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100757 inline void AdvanceToId(StackFrame::Id id);
758
Steve Blocka7e24c12009-10-30 11:49:00 +0000759 Iterator iterator_;
760};
761
762
763typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
764
765
766// NOTE: The stack trace frame iterator is an iterator that only
767// traverse proper JavaScript frames; that is JavaScript frames that
768// have proper JavaScript functions. This excludes the problematic
769// functions in runtime.js.
770class StackTraceFrameIterator: public JavaScriptFrameIterator {
771 public:
772 StackTraceFrameIterator();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100773 explicit StackTraceFrameIterator(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000774 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000775
776 private:
777 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000778};
779
780
781class SafeStackFrameIterator BASE_EMBEDDED {
782 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100783 SafeStackFrameIterator(Isolate* isolate,
784 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000785 Address low_bound, Address high_bound);
786
787 StackFrame* frame() const {
788 ASSERT(is_working_iterator_);
789 return iterator_.frame();
790 }
791
792 bool done() const { return iteration_done_ ? true : iterator_.done(); }
793
794 void Advance();
795 void Reset();
796
Ben Murdoch8b112d22011-06-08 16:22:53 +0100797 static bool is_active(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100798
Steve Blocka7e24c12009-10-30 11:49:00 +0000799 static bool IsWithinBounds(
800 Address low_bound, Address high_bound, Address addr) {
801 return low_bound <= addr && addr <= high_bound;
802 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000803
804 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100805 class StackAddressValidator {
806 public:
807 StackAddressValidator(Address low_bound, Address high_bound)
808 : low_bound_(low_bound), high_bound_(high_bound) { }
809 bool IsValid(Address addr) const {
810 return IsWithinBounds(low_bound_, high_bound_, addr);
811 }
812 private:
813 Address low_bound_;
814 Address high_bound_;
815 };
816
817 class ExitFrameValidator {
818 public:
819 explicit ExitFrameValidator(const StackAddressValidator& validator)
820 : validator_(validator) { }
821 ExitFrameValidator(Address low_bound, Address high_bound)
822 : validator_(low_bound, high_bound) { }
823 bool IsValidFP(Address fp);
824 private:
825 StackAddressValidator validator_;
826 };
827
Steve Blocka7e24c12009-10-30 11:49:00 +0000828 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100829 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000830 }
831 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
832 bool IsValidFrame(StackFrame* frame) const;
833 bool IsValidCaller(StackFrame* frame);
Steve Block44f0eee2011-05-26 01:26:41 +0100834 static bool IsValidTop(Isolate* isolate,
835 Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000836
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100837 // This is a nasty hack to make sure the active count is incremented
838 // before the constructor for the embedded iterator is invoked. This
839 // is needed because the constructor will start looking at frames
840 // right away and we need to make sure it doesn't start inspecting
841 // heap objects.
842 class ActiveCountMaintainer BASE_EMBEDDED {
843 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100844 explicit ActiveCountMaintainer(Isolate* isolate);
845 ~ActiveCountMaintainer();
846 private:
847 Isolate* isolate_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100848 };
849
850 ActiveCountMaintainer maintainer_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100851 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000852 const bool is_valid_top_;
853 const bool is_valid_fp_;
854 const bool is_working_iterator_;
855 bool iteration_done_;
856 StackFrameIterator iterator_;
857};
858
859
Steve Blocka7e24c12009-10-30 11:49:00 +0000860typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
861 SafeJavaScriptFrameIterator;
862
863
864class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
865 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100866 explicit SafeStackTraceFrameIterator(Isolate* isolate,
867 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000868 Address low_bound, Address high_bound);
869 void Advance();
870};
Steve Blocka7e24c12009-10-30 11:49:00 +0000871
872
873class StackFrameLocator BASE_EMBEDDED {
874 public:
875 // Find the nth JavaScript frame on the stack. The caller must
876 // guarantee that such a frame exists.
877 JavaScriptFrame* FindJavaScriptFrame(int n);
878
879 private:
880 StackFrameIterator iterator_;
881};
882
883
Steve Block6ded16b2010-05-10 14:33:55 +0100884// Reads all frames on the current stack and copies them into the current
885// zone memory.
886Vector<StackFrame*> CreateStackMap();
887
Steve Blocka7e24c12009-10-30 11:49:00 +0000888} } // namespace v8::internal
889
890#endif // V8_FRAMES_H_