blob: f542a92d96c453e2c1706d694fd66e092ca6ddad [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_FRAMES_H_
29#define V8_FRAMES_H_
30
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
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100117 inline Address* pc_address() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000118
119 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
120};
121
122
123#define STACK_FRAME_TYPE_LIST(V) \
124 V(ENTRY, EntryFrame) \
125 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
126 V(EXIT, ExitFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000127 V(JAVA_SCRIPT, JavaScriptFrame) \
Ben Murdochb0fe1622011-05-05 13:52:32 +0100128 V(OPTIMIZED, OptimizedFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000129 V(INTERNAL, InternalFrame) \
130 V(CONSTRUCT, ConstructFrame) \
131 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
132
133
134// Abstract base class for all stack frames.
135class StackFrame BASE_EMBEDDED {
136 public:
137#define DECLARE_TYPE(type, ignore) type,
138 enum Type {
139 NONE = 0,
140 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
141 NUMBER_OF_TYPES
142 };
143#undef DECLARE_TYPE
144
145 // Opaque data type for identifying stack frames. Used extensively
146 // by the debugger.
Iain Merrick75681382010-08-19 15:07:18 +0100147 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
148 // has correct value range (see Issue 830 for more details).
149 enum Id {
150 ID_MIN_VALUE = kMinInt,
151 ID_MAX_VALUE = kMaxInt,
152 NO_ID = 0
153 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000154
Steve Block053d10c2011-06-13 19:13:29 +0100155 // Used to mark the outermost JS entry frame.
156 enum JsFrameMarker {
157 INNER_JSENTRY_FRAME = 0,
158 OUTERMOST_JSENTRY_FRAME = 1
159 };
160
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100161 struct State {
162 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
163 Address sp;
164 Address fp;
165 Address* pc_address;
166 };
167
Ben Murdoch8b112d22011-06-08 16:22:53 +0100168 // Copy constructor; it breaks the connection to host iterator
169 // (as an iterator usually lives on stack).
Steve Block6ded16b2010-05-10 14:33:55 +0100170 StackFrame(const StackFrame& original) {
171 this->state_ = original.state_;
172 this->iterator_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100173 this->isolate_ = original.isolate_;
Steve Block6ded16b2010-05-10 14:33:55 +0100174 }
175
Steve Blocka7e24c12009-10-30 11:49:00 +0000176 // Type testers.
177 bool is_entry() const { return type() == ENTRY; }
178 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
179 bool is_exit() const { return type() == EXIT; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100180 bool is_optimized() const { return type() == OPTIMIZED; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000181 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
182 bool is_internal() const { return type() == INTERNAL; }
183 bool is_construct() const { return type() == CONSTRUCT; }
184 virtual bool is_standard() const { return false; }
185
Ben Murdochb0fe1622011-05-05 13:52:32 +0100186 bool is_java_script() const {
187 Type type = this->type();
188 return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
189 }
190
Steve Blocka7e24c12009-10-30 11:49:00 +0000191 // Accessors.
192 Address sp() const { return state_.sp; }
193 Address fp() const { return state_.fp; }
194 Address caller_sp() const { return GetCallerStackPointer(); }
195
196 Address pc() const { return *pc_address(); }
197 void set_pc(Address pc) { *pc_address() = pc; }
198
Steve Block6ded16b2010-05-10 14:33:55 +0100199 virtual void SetCallerFp(Address caller_fp) = 0;
200
Steve Blocka7e24c12009-10-30 11:49:00 +0000201 Address* pc_address() const { return state_.pc_address; }
202
203 // Get the id of this stack frame.
204 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
205
206 // Checks if this frame includes any stack handlers.
207 bool HasHandler() const;
208
209 // Get the type of this frame.
210 virtual Type type() const = 0;
211
212 // Get the code associated with this frame.
Iain Merrick75681382010-08-19 15:07:18 +0100213 // This method could be called during marking phase of GC.
214 virtual Code* unchecked_code() const = 0;
215
216 // Get the code associated with this frame.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100217 Code* LookupCode() const {
218 return GetContainingCode(isolate(), pc());
Steve Block44f0eee2011-05-26 01:26:41 +0100219 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100220
221 // Get the code object that contains the given pc.
Steve Block44f0eee2011-05-26 01:26:41 +0100222 static inline Code* GetContainingCode(Isolate* isolate, Address pc);
Steve Blocka7e24c12009-10-30 11:49:00 +0000223
Ben Murdochb0fe1622011-05-05 13:52:32 +0100224 // Get the code object containing the given pc and fill in the
225 // safepoint entry and the number of stack slots. The pc must be at
226 // a safepoint.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100227 static Code* GetSafepointData(Isolate* isolate,
228 Address pc,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100229 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100230 unsigned* stack_slots);
231
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100232 virtual void Iterate(ObjectVisitor* v) const = 0;
233 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000234
Steve Blocka7e24c12009-10-30 11:49:00 +0000235
236 // Printing support.
237 enum PrintMode { OVERVIEW, DETAILS };
238 virtual void Print(StringStream* accumulator,
239 PrintMode mode,
240 int index) const { }
241
242 protected:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100243 inline explicit StackFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000244 virtual ~StackFrame() { }
245
Ben Murdoch8b112d22011-06-08 16:22:53 +0100246 Isolate* isolate() const { return isolate_; }
247
Steve Blocka7e24c12009-10-30 11:49:00 +0000248 // Compute the stack pointer for the calling frame.
249 virtual Address GetCallerStackPointer() const = 0;
250
251 // Printing support.
252 static void PrintIndex(StringStream* accumulator,
253 PrintMode mode,
254 int index);
255
256 // Get the top handler from the current stack iterator.
257 inline StackHandler* top_handler() const;
258
259 // Compute the stack frame type for the given state.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100260 static Type ComputeType(Isolate* isolate, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000261
262 private:
263 const StackFrameIterator* iterator_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100264 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000265 State state_;
266
267 // Fill in the state of the calling frame.
268 virtual void ComputeCallerState(State* state) const = 0;
269
270 // Get the type and the state of the calling frame.
271 virtual Type GetCallerState(State* state) const;
272
Ben Murdoch8b112d22011-06-08 16:22:53 +0100273 static const intptr_t kIsolateTag = 1;
274
Steve Blocka7e24c12009-10-30 11:49:00 +0000275 friend class StackFrameIterator;
276 friend class StackHandlerIterator;
277 friend class SafeStackFrameIterator;
278
Steve Block6ded16b2010-05-10 14:33:55 +0100279 private:
280 void operator=(const StackFrame& original);
Steve Blocka7e24c12009-10-30 11:49:00 +0000281};
282
283
284// Entry frames are used to enter JavaScript execution from C.
285class EntryFrame: public StackFrame {
286 public:
287 virtual Type type() const { return ENTRY; }
288
Iain Merrick75681382010-08-19 15:07:18 +0100289 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000290
291 // Garbage collection support.
292 virtual void Iterate(ObjectVisitor* v) const;
293
294 static EntryFrame* cast(StackFrame* frame) {
295 ASSERT(frame->is_entry());
296 return static_cast<EntryFrame*>(frame);
297 }
Steve Block6ded16b2010-05-10 14:33:55 +0100298 virtual void SetCallerFp(Address caller_fp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000299
300 protected:
301 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
302
303 // The caller stack pointer for entry frames is always zero. The
304 // real information about the caller frame is available through the
305 // link to the top exit frame.
306 virtual Address GetCallerStackPointer() const { return 0; }
307
308 private:
309 virtual void ComputeCallerState(State* state) const;
310 virtual Type GetCallerState(State* state) const;
311
312 friend class StackFrameIterator;
313};
314
315
316class EntryConstructFrame: public EntryFrame {
317 public:
318 virtual Type type() const { return ENTRY_CONSTRUCT; }
319
Iain Merrick75681382010-08-19 15:07:18 +0100320 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000321
322 static EntryConstructFrame* cast(StackFrame* frame) {
323 ASSERT(frame->is_entry_construct());
324 return static_cast<EntryConstructFrame*>(frame);
325 }
326
327 protected:
328 explicit EntryConstructFrame(StackFrameIterator* iterator)
329 : EntryFrame(iterator) { }
330
331 private:
332 friend class StackFrameIterator;
333};
334
335
336// Exit frames are used to exit JavaScript execution and go to C.
337class ExitFrame: public StackFrame {
338 public:
339 virtual Type type() const { return EXIT; }
340
Iain Merrick75681382010-08-19 15:07:18 +0100341 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000342
Steve Blockd0582a62009-12-15 09:54:21 +0000343 Object*& code_slot() const;
344
Steve Blocka7e24c12009-10-30 11:49:00 +0000345 // Garbage collection support.
346 virtual void Iterate(ObjectVisitor* v) const;
347
Steve Block6ded16b2010-05-10 14:33:55 +0100348 virtual void SetCallerFp(Address caller_fp);
349
Steve Blocka7e24c12009-10-30 11:49:00 +0000350 static ExitFrame* cast(StackFrame* frame) {
351 ASSERT(frame->is_exit());
352 return static_cast<ExitFrame*>(frame);
353 }
354
355 // Compute the state and type of an exit frame given a frame
356 // pointer. Used when constructing the first stack frame seen by an
357 // iterator and the frames following entry frames.
358 static Type GetStateForFramePointer(Address fp, State* state);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100359 static Address ComputeStackPointer(Address fp);
360 static void FillState(Address fp, Address sp, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000361
362 protected:
363 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
364
365 virtual Address GetCallerStackPointer() const;
366
367 private:
368 virtual void ComputeCallerState(State* state) const;
369
370 friend class StackFrameIterator;
371};
372
373
Steve Blocka7e24c12009-10-30 11:49:00 +0000374class StandardFrame: public StackFrame {
375 public:
376 // Testers.
377 virtual bool is_standard() const { return true; }
378
379 // Accessors.
380 inline Object* context() const;
381
382 // Access the expressions in the stack frame including locals.
383 inline Object* GetExpression(int index) const;
384 inline void SetExpression(int index, Object* value);
385 int ComputeExpressionsCount() const;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000386 static Object* GetExpression(Address fp, int index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000387
Steve Block6ded16b2010-05-10 14:33:55 +0100388 virtual void SetCallerFp(Address caller_fp);
389
Steve Blocka7e24c12009-10-30 11:49:00 +0000390 static StandardFrame* cast(StackFrame* frame) {
391 ASSERT(frame->is_standard());
392 return static_cast<StandardFrame*>(frame);
393 }
394
395 protected:
396 explicit StandardFrame(StackFrameIterator* iterator)
397 : StackFrame(iterator) { }
398
399 virtual void ComputeCallerState(State* state) const;
400
401 // Accessors.
402 inline Address caller_fp() const;
403 inline Address caller_pc() const;
404
405 // Computes the address of the PC field in the standard frame given
406 // by the provided frame pointer.
407 static inline Address ComputePCAddress(Address fp);
408
409 // Iterate over expression stack including stack handlers, locals,
410 // and parts of the fixed part including context and code fields.
411 void IterateExpressions(ObjectVisitor* v) const;
412
413 // Returns the address of the n'th expression stack element.
414 Address GetExpressionAddress(int n) const;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000415 static Address GetExpressionAddress(Address fp, int n);
Steve Blocka7e24c12009-10-30 11:49:00 +0000416
417 // Determines if the n'th expression stack element is in a stack
418 // handler or not. Requires traversing all handlers in this frame.
419 bool IsExpressionInsideHandler(int n) const;
420
421 // Determines if the standard frame for the given frame pointer is
422 // an arguments adaptor frame.
423 static inline bool IsArgumentsAdaptorFrame(Address fp);
424
425 // Determines if the standard frame for the given frame pointer is a
426 // construct frame.
427 static inline bool IsConstructFrame(Address fp);
428
429 private:
430 friend class StackFrame;
Kristian Monsen25f61362010-05-21 11:50:48 +0100431 friend class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000432};
433
434
Ben Murdochb0fe1622011-05-05 13:52:32 +0100435class FrameSummary BASE_EMBEDDED {
436 public:
437 FrameSummary(Object* receiver,
438 JSFunction* function,
439 Code* code,
440 int offset,
441 bool is_constructor)
442 : receiver_(receiver),
443 function_(function),
444 code_(code),
445 offset_(offset),
446 is_constructor_(is_constructor) { }
447 Handle<Object> receiver() { return receiver_; }
448 Handle<JSFunction> function() { return function_; }
449 Handle<Code> code() { return code_; }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100450 Address pc() { return code_->address() + offset_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100451 int offset() { return offset_; }
452 bool is_constructor() { return is_constructor_; }
453
454 void Print();
455
456 private:
457 Handle<Object> receiver_;
458 Handle<JSFunction> function_;
459 Handle<Code> code_;
460 int offset_;
461 bool is_constructor_;
462};
463
464
Steve Blocka7e24c12009-10-30 11:49:00 +0000465class JavaScriptFrame: public StandardFrame {
466 public:
467 virtual Type type() const { return JAVA_SCRIPT; }
468
469 // Accessors.
470 inline Object* function() const;
471 inline Object* receiver() const;
472 inline void set_receiver(Object* value);
473
474 // Access the parameters.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100475 inline Address GetParameterSlot(int index) const;
476 inline Object* GetParameter(int index) const;
477 inline int ComputeParametersCount() const {
478 return GetNumberOfIncomingArguments();
479 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000480
Steve Blocka7e24c12009-10-30 11:49:00 +0000481 // Check if this frame is a constructor frame invoked through 'new'.
482 bool IsConstructor() const;
483
484 // Check if this frame has "adapted" arguments in the sense that the
485 // actual passed arguments are available in an arguments adaptor
486 // frame below it on the stack.
487 inline bool has_adapted_arguments() const;
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000488 int GetArgumentsLength() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000489
490 // Garbage collection support.
491 virtual void Iterate(ObjectVisitor* v) const;
492
493 // Printing support.
494 virtual void Print(StringStream* accumulator,
495 PrintMode mode,
496 int index) const;
497
498 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100499 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000500
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000501 // Returns the levels of inlining for this frame.
502 virtual int GetInlineCount() { return 1; }
503
Ben Murdochb0fe1622011-05-05 13:52:32 +0100504 // Return a list with JSFunctions of this frame.
505 virtual void GetFunctions(List<JSFunction*>* functions);
506
507 // Build a list with summaries for this frame including all inlined frames.
508 virtual void Summarize(List<FrameSummary>* frames);
509
Steve Blocka7e24c12009-10-30 11:49:00 +0000510 static JavaScriptFrame* cast(StackFrame* frame) {
511 ASSERT(frame->is_java_script());
512 return static_cast<JavaScriptFrame*>(frame);
513 }
514
515 protected:
516 explicit JavaScriptFrame(StackFrameIterator* iterator)
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100517 : StandardFrame(iterator) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000518
519 virtual Address GetCallerStackPointer() const;
520
Ben Murdoch8b112d22011-06-08 16:22:53 +0100521 virtual int GetNumberOfIncomingArguments() const;
522
Ben Murdochb0fe1622011-05-05 13:52:32 +0100523 // Garbage collection support. Iterates over incoming arguments,
524 // receiver, and any callee-saved registers.
525 void IterateArguments(ObjectVisitor* v) const;
526
Steve Blocka7e24c12009-10-30 11:49:00 +0000527 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000528 inline Object* function_slot_object() const;
529
530 friend class StackFrameIterator;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100531 friend class StackTracer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000532};
533
534
Ben Murdochb0fe1622011-05-05 13:52:32 +0100535class OptimizedFrame : public JavaScriptFrame {
536 public:
537 virtual Type type() const { return OPTIMIZED; }
538
539 // GC support.
540 virtual void Iterate(ObjectVisitor* v) const;
541
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000542 virtual int GetInlineCount();
543
Ben Murdochb0fe1622011-05-05 13:52:32 +0100544 // Return a list with JSFunctions of this frame.
545 // The functions are ordered bottom-to-top (i.e. functions.last()
546 // is the top-most activation)
547 virtual void GetFunctions(List<JSFunction*>* functions);
548
549 virtual void Summarize(List<FrameSummary>* frames);
550
551 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
552
553 protected:
554 explicit OptimizedFrame(StackFrameIterator* iterator)
555 : JavaScriptFrame(iterator) { }
556
557 private:
558 friend class StackFrameIterator;
559};
560
561
Steve Blocka7e24c12009-10-30 11:49:00 +0000562// Arguments adaptor frames are automatically inserted below
563// JavaScript frames when the actual number of parameters does not
564// match the formal number of parameters.
565class ArgumentsAdaptorFrame: public JavaScriptFrame {
566 public:
567 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
568
569 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100570 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000571
572 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
573 ASSERT(frame->is_arguments_adaptor());
574 return static_cast<ArgumentsAdaptorFrame*>(frame);
575 }
576
577 // Printing support.
578 virtual void Print(StringStream* accumulator,
579 PrintMode mode,
580 int index) const;
581 protected:
582 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
583 : JavaScriptFrame(iterator) { }
584
Ben Murdoch8b112d22011-06-08 16:22:53 +0100585 virtual int GetNumberOfIncomingArguments() const {
586 return Smi::cast(GetExpression(0))->value();
587 }
588
Steve Blocka7e24c12009-10-30 11:49:00 +0000589 virtual Address GetCallerStackPointer() const;
590
591 private:
592 friend class StackFrameIterator;
593};
594
595
596class InternalFrame: public StandardFrame {
597 public:
598 virtual Type type() const { return INTERNAL; }
599
600 // Garbage collection support.
601 virtual void Iterate(ObjectVisitor* v) const;
602
603 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100604 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000605
606 static InternalFrame* cast(StackFrame* frame) {
607 ASSERT(frame->is_internal());
608 return static_cast<InternalFrame*>(frame);
609 }
610
611 protected:
612 explicit InternalFrame(StackFrameIterator* iterator)
613 : StandardFrame(iterator) { }
614
615 virtual Address GetCallerStackPointer() const;
616
617 private:
618 friend class StackFrameIterator;
619};
620
621
622// Construct frames are special trampoline frames introduced to handle
623// function invocations through 'new'.
624class ConstructFrame: public InternalFrame {
625 public:
626 virtual Type type() const { return CONSTRUCT; }
627
628 static ConstructFrame* cast(StackFrame* frame) {
629 ASSERT(frame->is_construct());
630 return static_cast<ConstructFrame*>(frame);
631 }
632
633 protected:
634 explicit ConstructFrame(StackFrameIterator* iterator)
635 : InternalFrame(iterator) { }
636
637 private:
638 friend class StackFrameIterator;
639};
640
641
642class StackFrameIterator BASE_EMBEDDED {
643 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100644 // An iterator that iterates over the current thread's stack,
645 // and uses current isolate.
Steve Blocka7e24c12009-10-30 11:49:00 +0000646 StackFrameIterator();
647
Ben Murdoch8b112d22011-06-08 16:22:53 +0100648 // An iterator that iterates over the isolate's current thread's stack,
649 explicit StackFrameIterator(Isolate* isolate);
650
Steve Blocka7e24c12009-10-30 11:49:00 +0000651 // An iterator that iterates over a given thread's stack.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100652 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
Steve Blocka7e24c12009-10-30 11:49:00 +0000653
654 // An iterator that can start from a given FP address.
655 // If use_top, then work as usual, if fp isn't NULL, use it,
656 // otherwise, do nothing.
Steve Block44f0eee2011-05-26 01:26:41 +0100657 StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000658
659 StackFrame* frame() const {
660 ASSERT(!done());
661 return frame_;
662 }
663
Ben Murdoch8b112d22011-06-08 16:22:53 +0100664 Isolate* isolate() const { return isolate_; }
665
Steve Blocka7e24c12009-10-30 11:49:00 +0000666 bool done() const { return frame_ == NULL; }
667 void Advance() { (this->*advance_)(); }
668
669 // Go back to the first frame.
670 void Reset();
671
672 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100673 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000674#define DECLARE_SINGLETON(ignore, type) type type##_;
675 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
676#undef DECLARE_SINGLETON
677 StackFrame* frame_;
678 StackHandler* handler_;
679 ThreadLocalTop* thread_;
680 Address fp_;
681 Address sp_;
682 void (StackFrameIterator::*advance_)();
683
684 StackHandler* handler() const {
685 ASSERT(!done());
686 return handler_;
687 }
688
689 // Get the type-specific frame singleton in a given state.
690 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
691 // A helper function, can return a NULL pointer.
692 StackFrame* SingletonFor(StackFrame::Type type);
693
694 void AdvanceWithHandler();
695 void AdvanceWithoutHandler();
696
697 friend class StackFrame;
698 friend class SafeStackFrameIterator;
699 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
700};
701
702
703// Iterator that supports iterating through all JavaScript frames.
704template<typename Iterator>
705class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
706 public:
707 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
708
Ben Murdoch8b112d22011-06-08 16:22:53 +0100709 inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000710
711 // Skip frames until the frame with the given id is reached.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100712 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
713
714 inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
Steve Blocka7e24c12009-10-30 11:49:00 +0000715
716 JavaScriptFrameIteratorTemp(Address fp, Address sp,
717 Address low_bound, Address high_bound) :
718 iterator_(fp, sp, low_bound, high_bound) {
719 if (!done()) Advance();
720 }
721
Steve Block44f0eee2011-05-26 01:26:41 +0100722 JavaScriptFrameIteratorTemp(Isolate* isolate,
723 Address fp, Address sp,
724 Address low_bound, Address high_bound) :
725 iterator_(isolate, fp, sp, low_bound, high_bound) {
726 if (!done()) Advance();
727 }
728
Steve Blocka7e24c12009-10-30 11:49:00 +0000729 inline JavaScriptFrame* frame() const;
730
731 bool done() const { return iterator_.done(); }
732 void Advance();
733
734 // Advance to the frame holding the arguments for the current
735 // frame. This only affects the current frame if it has adapted
736 // arguments.
737 void AdvanceToArgumentsFrame();
738
739 // Go back to the first frame.
740 void Reset();
741
742 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100743 inline void AdvanceToId(StackFrame::Id id);
744
Steve Blocka7e24c12009-10-30 11:49:00 +0000745 Iterator iterator_;
746};
747
748
749typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
750
751
752// NOTE: The stack trace frame iterator is an iterator that only
753// traverse proper JavaScript frames; that is JavaScript frames that
754// have proper JavaScript functions. This excludes the problematic
755// functions in runtime.js.
756class StackTraceFrameIterator: public JavaScriptFrameIterator {
757 public:
758 StackTraceFrameIterator();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100759 explicit StackTraceFrameIterator(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000760 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000761
762 private:
763 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000764};
765
766
767class SafeStackFrameIterator BASE_EMBEDDED {
768 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100769 SafeStackFrameIterator(Isolate* isolate,
770 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000771 Address low_bound, Address high_bound);
772
773 StackFrame* frame() const {
774 ASSERT(is_working_iterator_);
775 return iterator_.frame();
776 }
777
778 bool done() const { return iteration_done_ ? true : iterator_.done(); }
779
780 void Advance();
781 void Reset();
782
Ben Murdoch8b112d22011-06-08 16:22:53 +0100783 static bool is_active(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100784
Steve Blocka7e24c12009-10-30 11:49:00 +0000785 static bool IsWithinBounds(
786 Address low_bound, Address high_bound, Address addr) {
787 return low_bound <= addr && addr <= high_bound;
788 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000789
790 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100791 class StackAddressValidator {
792 public:
793 StackAddressValidator(Address low_bound, Address high_bound)
794 : low_bound_(low_bound), high_bound_(high_bound) { }
795 bool IsValid(Address addr) const {
796 return IsWithinBounds(low_bound_, high_bound_, addr);
797 }
798 private:
799 Address low_bound_;
800 Address high_bound_;
801 };
802
803 class ExitFrameValidator {
804 public:
805 explicit ExitFrameValidator(const StackAddressValidator& validator)
806 : validator_(validator) { }
807 ExitFrameValidator(Address low_bound, Address high_bound)
808 : validator_(low_bound, high_bound) { }
809 bool IsValidFP(Address fp);
810 private:
811 StackAddressValidator validator_;
812 };
813
Steve Blocka7e24c12009-10-30 11:49:00 +0000814 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100815 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000816 }
817 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
818 bool IsValidFrame(StackFrame* frame) const;
819 bool IsValidCaller(StackFrame* frame);
Steve Block44f0eee2011-05-26 01:26:41 +0100820 static bool IsValidTop(Isolate* isolate,
821 Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000822
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100823 // This is a nasty hack to make sure the active count is incremented
824 // before the constructor for the embedded iterator is invoked. This
825 // is needed because the constructor will start looking at frames
826 // right away and we need to make sure it doesn't start inspecting
827 // heap objects.
828 class ActiveCountMaintainer BASE_EMBEDDED {
829 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100830 explicit ActiveCountMaintainer(Isolate* isolate);
831 ~ActiveCountMaintainer();
832 private:
833 Isolate* isolate_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100834 };
835
836 ActiveCountMaintainer maintainer_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100837 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000838 const bool is_valid_top_;
839 const bool is_valid_fp_;
840 const bool is_working_iterator_;
841 bool iteration_done_;
842 StackFrameIterator iterator_;
843};
844
845
Steve Blocka7e24c12009-10-30 11:49:00 +0000846typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
847 SafeJavaScriptFrameIterator;
848
849
850class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
851 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100852 explicit SafeStackTraceFrameIterator(Isolate* isolate,
853 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000854 Address low_bound, Address high_bound);
855 void Advance();
856};
Steve Blocka7e24c12009-10-30 11:49:00 +0000857
858
859class StackFrameLocator BASE_EMBEDDED {
860 public:
861 // Find the nth JavaScript frame on the stack. The caller must
862 // guarantee that such a frame exists.
863 JavaScriptFrame* FindJavaScriptFrame(int n);
864
865 private:
866 StackFrameIterator iterator_;
867};
868
869
Steve Block6ded16b2010-05-10 14:33:55 +0100870// Reads all frames on the current stack and copies them into the current
871// zone memory.
872Vector<StackFrame*> CreateStackMap();
873
Steve Blocka7e24c12009-10-30 11:49:00 +0000874} } // namespace v8::internal
875
876#endif // V8_FRAMES_H_