blob: da9009be3020e6448e87733928660cf115e43fe6 [file] [log] [blame]
Steve Blocka7e24c12009-10-30 11:49:00 +00001// Copyright 2006-2008 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#ifndef V8_FRAMES_H_
29#define V8_FRAMES_H_
30
Steve Block44f0eee2011-05-26 01:26:41 +010031#include "handles.h"
Ben Murdochb8e0da22011-05-16 14:20:40 +010032#include "safepoint-table.h"
33
Steve Blocka7e24c12009-10-30 11:49:00 +000034namespace v8 {
35namespace internal {
36
37typedef uint32_t RegList;
38
39// Get the number of registers in a given register list.
40int NumRegs(RegList list);
41
42// Return the code of the n-th saved register available to JavaScript.
43int JSCallerSavedCode(int n);
44
45
46// Forward declarations.
47class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +000048class ThreadLocalTop;
Steve Block44f0eee2011-05-26 01:26:41 +010049class Isolate;
Steve Blocka7e24c12009-10-30 11:49:00 +000050
Steve Block44f0eee2011-05-26 01:26:41 +010051class PcToCodeCache {
Kristian Monsen80d68ea2010-09-08 11:05:35 +010052 public:
53 struct PcToCodeCacheEntry {
54 Address pc;
55 Code* code;
Ben Murdochb8e0da22011-05-16 14:20:40 +010056 SafepointEntry safepoint_entry;
Kristian Monsen80d68ea2010-09-08 11:05:35 +010057 };
58
Steve Block44f0eee2011-05-26 01:26:41 +010059 explicit PcToCodeCache(Isolate* isolate) : isolate_(isolate) {
60 Flush();
Kristian Monsen80d68ea2010-09-08 11:05:35 +010061 }
62
Steve Block44f0eee2011-05-26 01:26:41 +010063 Code* GcSafeFindCodeForPc(Address pc);
64 Code* GcSafeCastToCode(HeapObject* object, Address pc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010065
Steve Block44f0eee2011-05-26 01:26:41 +010066 void Flush() {
Kristian Monsen80d68ea2010-09-08 11:05:35 +010067 memset(&cache_[0], 0, sizeof(cache_));
68 }
69
Steve Block44f0eee2011-05-26 01:26:41 +010070 PcToCodeCacheEntry* GetCacheEntry(Address pc);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010071
72 private:
Steve Block44f0eee2011-05-26 01:26:41 +010073 PcToCodeCacheEntry* cache(int index) { return &cache_[index]; }
74
75 Isolate* isolate_;
76
Kristian Monsen0d5e1162010-09-30 15:31:59 +010077 static const int kPcToCodeCacheSize = 1024;
Steve Block44f0eee2011-05-26 01:26:41 +010078 PcToCodeCacheEntry cache_[kPcToCodeCacheSize];
79
80 DISALLOW_COPY_AND_ASSIGN(PcToCodeCache);
Kristian Monsen80d68ea2010-09-08 11:05:35 +010081};
82
83
Steve Blocka7e24c12009-10-30 11:49:00 +000084class StackHandler BASE_EMBEDDED {
85 public:
86 enum State {
87 ENTRY,
88 TRY_CATCH,
89 TRY_FINALLY
90 };
91
92 // Get the address of this stack handler.
93 inline Address address() const;
94
95 // Get the next stack handler in the chain.
96 inline StackHandler* next() const;
97
98 // Tells whether the given address is inside this handler.
99 inline bool includes(Address address) const;
100
101 // Garbage collection support.
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100102 inline void Iterate(ObjectVisitor* v, Code* holder) const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000103
104 // Conversion support.
105 static inline StackHandler* FromAddress(Address address);
106
107 // Testers
108 bool is_entry() { return state() == ENTRY; }
109 bool is_try_catch() { return state() == TRY_CATCH; }
110 bool is_try_finally() { return state() == TRY_FINALLY; }
111
Steve Blocka7e24c12009-10-30 11:49:00 +0000112 private:
113 // Accessors.
114 inline State state() const;
115
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100116 inline Address* pc_address() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000117
118 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
119};
120
121
122#define STACK_FRAME_TYPE_LIST(V) \
123 V(ENTRY, EntryFrame) \
124 V(ENTRY_CONSTRUCT, EntryConstructFrame) \
125 V(EXIT, ExitFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000126 V(JAVA_SCRIPT, JavaScriptFrame) \
Ben Murdochb0fe1622011-05-05 13:52:32 +0100127 V(OPTIMIZED, OptimizedFrame) \
Steve Blocka7e24c12009-10-30 11:49:00 +0000128 V(INTERNAL, InternalFrame) \
129 V(CONSTRUCT, ConstructFrame) \
130 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
131
132
133// Abstract base class for all stack frames.
134class StackFrame BASE_EMBEDDED {
135 public:
136#define DECLARE_TYPE(type, ignore) type,
137 enum Type {
138 NONE = 0,
139 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
140 NUMBER_OF_TYPES
141 };
142#undef DECLARE_TYPE
143
144 // Opaque data type for identifying stack frames. Used extensively
145 // by the debugger.
Iain Merrick75681382010-08-19 15:07:18 +0100146 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
147 // has correct value range (see Issue 830 for more details).
148 enum Id {
149 ID_MIN_VALUE = kMinInt,
150 ID_MAX_VALUE = kMaxInt,
151 NO_ID = 0
152 };
Steve Blocka7e24c12009-10-30 11:49:00 +0000153
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100154 struct State {
155 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
156 Address sp;
157 Address fp;
158 Address* pc_address;
159 };
160
Ben Murdoch8b112d22011-06-08 16:22:53 +0100161 // Copy constructor; it breaks the connection to host iterator
162 // (as an iterator usually lives on stack).
Steve Block6ded16b2010-05-10 14:33:55 +0100163 StackFrame(const StackFrame& original) {
164 this->state_ = original.state_;
165 this->iterator_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100166 this->isolate_ = original.isolate_;
Steve Block6ded16b2010-05-10 14:33:55 +0100167 }
168
Steve Blocka7e24c12009-10-30 11:49:00 +0000169 // Type testers.
170 bool is_entry() const { return type() == ENTRY; }
171 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
172 bool is_exit() const { return type() == EXIT; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100173 bool is_optimized() const { return type() == OPTIMIZED; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000174 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
175 bool is_internal() const { return type() == INTERNAL; }
176 bool is_construct() const { return type() == CONSTRUCT; }
177 virtual bool is_standard() const { return false; }
178
Ben Murdochb0fe1622011-05-05 13:52:32 +0100179 bool is_java_script() const {
180 Type type = this->type();
181 return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
182 }
183
Steve Blocka7e24c12009-10-30 11:49:00 +0000184 // Accessors.
185 Address sp() const { return state_.sp; }
186 Address fp() const { return state_.fp; }
187 Address caller_sp() const { return GetCallerStackPointer(); }
188
189 Address pc() const { return *pc_address(); }
190 void set_pc(Address pc) { *pc_address() = pc; }
191
Steve Block6ded16b2010-05-10 14:33:55 +0100192 virtual void SetCallerFp(Address caller_fp) = 0;
193
Steve Blocka7e24c12009-10-30 11:49:00 +0000194 Address* pc_address() const { return state_.pc_address; }
195
196 // Get the id of this stack frame.
197 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
198
199 // Checks if this frame includes any stack handlers.
200 bool HasHandler() const;
201
202 // Get the type of this frame.
203 virtual Type type() const = 0;
204
205 // Get the code associated with this frame.
Iain Merrick75681382010-08-19 15:07:18 +0100206 // This method could be called during marking phase of GC.
207 virtual Code* unchecked_code() const = 0;
208
209 // Get the code associated with this frame.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100210 Code* LookupCode() const {
211 return GetContainingCode(isolate(), pc());
Steve Block44f0eee2011-05-26 01:26:41 +0100212 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100213
214 // Get the code object that contains the given pc.
Steve Block44f0eee2011-05-26 01:26:41 +0100215 static inline Code* GetContainingCode(Isolate* isolate, Address pc);
Steve Blocka7e24c12009-10-30 11:49:00 +0000216
Ben Murdochb0fe1622011-05-05 13:52:32 +0100217 // Get the code object containing the given pc and fill in the
218 // safepoint entry and the number of stack slots. The pc must be at
219 // a safepoint.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100220 static Code* GetSafepointData(Isolate* isolate,
221 Address pc,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100222 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100223 unsigned* stack_slots);
224
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100225 virtual void Iterate(ObjectVisitor* v) const = 0;
226 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000227
Steve Blocka7e24c12009-10-30 11:49:00 +0000228
229 // Printing support.
230 enum PrintMode { OVERVIEW, DETAILS };
231 virtual void Print(StringStream* accumulator,
232 PrintMode mode,
233 int index) const { }
234
235 protected:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100236 inline explicit StackFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000237 virtual ~StackFrame() { }
238
Ben Murdoch8b112d22011-06-08 16:22:53 +0100239 Isolate* isolate() const { return isolate_; }
240
Steve Blocka7e24c12009-10-30 11:49:00 +0000241 // Compute the stack pointer for the calling frame.
242 virtual Address GetCallerStackPointer() const = 0;
243
244 // Printing support.
245 static void PrintIndex(StringStream* accumulator,
246 PrintMode mode,
247 int index);
248
249 // Get the top handler from the current stack iterator.
250 inline StackHandler* top_handler() const;
251
252 // Compute the stack frame type for the given state.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100253 static Type ComputeType(Isolate* isolate, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000254
255 private:
256 const StackFrameIterator* iterator_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100257 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000258 State state_;
259
260 // Fill in the state of the calling frame.
261 virtual void ComputeCallerState(State* state) const = 0;
262
263 // Get the type and the state of the calling frame.
264 virtual Type GetCallerState(State* state) const;
265
Ben Murdoch8b112d22011-06-08 16:22:53 +0100266 static const intptr_t kIsolateTag = 1;
267
Steve Blocka7e24c12009-10-30 11:49:00 +0000268 friend class StackFrameIterator;
269 friend class StackHandlerIterator;
270 friend class SafeStackFrameIterator;
271
Steve Block6ded16b2010-05-10 14:33:55 +0100272 private:
273 void operator=(const StackFrame& original);
Steve Blocka7e24c12009-10-30 11:49:00 +0000274};
275
276
277// Entry frames are used to enter JavaScript execution from C.
278class EntryFrame: public StackFrame {
279 public:
280 virtual Type type() const { return ENTRY; }
281
Iain Merrick75681382010-08-19 15:07:18 +0100282 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000283
284 // Garbage collection support.
285 virtual void Iterate(ObjectVisitor* v) const;
286
287 static EntryFrame* cast(StackFrame* frame) {
288 ASSERT(frame->is_entry());
289 return static_cast<EntryFrame*>(frame);
290 }
Steve Block6ded16b2010-05-10 14:33:55 +0100291 virtual void SetCallerFp(Address caller_fp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000292
293 protected:
294 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
295
296 // The caller stack pointer for entry frames is always zero. The
297 // real information about the caller frame is available through the
298 // link to the top exit frame.
299 virtual Address GetCallerStackPointer() const { return 0; }
300
301 private:
302 virtual void ComputeCallerState(State* state) const;
303 virtual Type GetCallerState(State* state) const;
304
305 friend class StackFrameIterator;
306};
307
308
309class EntryConstructFrame: public EntryFrame {
310 public:
311 virtual Type type() const { return ENTRY_CONSTRUCT; }
312
Iain Merrick75681382010-08-19 15:07:18 +0100313 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000314
315 static EntryConstructFrame* cast(StackFrame* frame) {
316 ASSERT(frame->is_entry_construct());
317 return static_cast<EntryConstructFrame*>(frame);
318 }
319
320 protected:
321 explicit EntryConstructFrame(StackFrameIterator* iterator)
322 : EntryFrame(iterator) { }
323
324 private:
325 friend class StackFrameIterator;
326};
327
328
329// Exit frames are used to exit JavaScript execution and go to C.
330class ExitFrame: public StackFrame {
331 public:
332 virtual Type type() const { return EXIT; }
333
Iain Merrick75681382010-08-19 15:07:18 +0100334 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000335
Steve Blockd0582a62009-12-15 09:54:21 +0000336 Object*& code_slot() const;
337
Steve Blocka7e24c12009-10-30 11:49:00 +0000338 // Garbage collection support.
339 virtual void Iterate(ObjectVisitor* v) const;
340
Steve Block6ded16b2010-05-10 14:33:55 +0100341 virtual void SetCallerFp(Address caller_fp);
342
Steve Blocka7e24c12009-10-30 11:49:00 +0000343 static ExitFrame* cast(StackFrame* frame) {
344 ASSERT(frame->is_exit());
345 return static_cast<ExitFrame*>(frame);
346 }
347
348 // Compute the state and type of an exit frame given a frame
349 // pointer. Used when constructing the first stack frame seen by an
350 // iterator and the frames following entry frames.
351 static Type GetStateForFramePointer(Address fp, State* state);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100352 static Address ComputeStackPointer(Address fp);
353 static void FillState(Address fp, Address sp, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000354
355 protected:
356 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
357
358 virtual Address GetCallerStackPointer() const;
359
360 private:
361 virtual void ComputeCallerState(State* state) const;
362
363 friend class StackFrameIterator;
364};
365
366
Steve Blocka7e24c12009-10-30 11:49:00 +0000367class StandardFrame: public StackFrame {
368 public:
369 // Testers.
370 virtual bool is_standard() const { return true; }
371
372 // Accessors.
373 inline Object* context() const;
374
375 // Access the expressions in the stack frame including locals.
376 inline Object* GetExpression(int index) const;
377 inline void SetExpression(int index, Object* value);
378 int ComputeExpressionsCount() const;
379
Steve Block6ded16b2010-05-10 14:33:55 +0100380 virtual void SetCallerFp(Address caller_fp);
381
Steve Blocka7e24c12009-10-30 11:49:00 +0000382 static StandardFrame* cast(StackFrame* frame) {
383 ASSERT(frame->is_standard());
384 return static_cast<StandardFrame*>(frame);
385 }
386
387 protected:
388 explicit StandardFrame(StackFrameIterator* iterator)
389 : StackFrame(iterator) { }
390
391 virtual void ComputeCallerState(State* state) const;
392
393 // Accessors.
394 inline Address caller_fp() const;
395 inline Address caller_pc() const;
396
397 // Computes the address of the PC field in the standard frame given
398 // by the provided frame pointer.
399 static inline Address ComputePCAddress(Address fp);
400
401 // Iterate over expression stack including stack handlers, locals,
402 // and parts of the fixed part including context and code fields.
403 void IterateExpressions(ObjectVisitor* v) const;
404
405 // Returns the address of the n'th expression stack element.
406 Address GetExpressionAddress(int n) const;
407
408 // Determines if the n'th expression stack element is in a stack
409 // handler or not. Requires traversing all handlers in this frame.
410 bool IsExpressionInsideHandler(int n) const;
411
412 // Determines if the standard frame for the given frame pointer is
413 // an arguments adaptor frame.
414 static inline bool IsArgumentsAdaptorFrame(Address fp);
415
416 // Determines if the standard frame for the given frame pointer is a
417 // construct frame.
418 static inline bool IsConstructFrame(Address fp);
419
420 private:
421 friend class StackFrame;
Kristian Monsen25f61362010-05-21 11:50:48 +0100422 friend class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000423};
424
425
Ben Murdochb0fe1622011-05-05 13:52:32 +0100426class FrameSummary BASE_EMBEDDED {
427 public:
428 FrameSummary(Object* receiver,
429 JSFunction* function,
430 Code* code,
431 int offset,
432 bool is_constructor)
433 : receiver_(receiver),
434 function_(function),
435 code_(code),
436 offset_(offset),
437 is_constructor_(is_constructor) { }
438 Handle<Object> receiver() { return receiver_; }
439 Handle<JSFunction> function() { return function_; }
440 Handle<Code> code() { return code_; }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100441 Address pc() { return code_->address() + offset_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100442 int offset() { return offset_; }
443 bool is_constructor() { return is_constructor_; }
444
445 void Print();
446
447 private:
448 Handle<Object> receiver_;
449 Handle<JSFunction> function_;
450 Handle<Code> code_;
451 int offset_;
452 bool is_constructor_;
453};
454
455
Steve Blocka7e24c12009-10-30 11:49:00 +0000456class JavaScriptFrame: public StandardFrame {
457 public:
458 virtual Type type() const { return JAVA_SCRIPT; }
459
460 // Accessors.
461 inline Object* function() const;
462 inline Object* receiver() const;
463 inline void set_receiver(Object* value);
464
465 // Access the parameters.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100466 inline Address GetParameterSlot(int index) const;
467 inline Object* GetParameter(int index) const;
468 inline int ComputeParametersCount() const {
469 return GetNumberOfIncomingArguments();
470 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000471
Steve Blocka7e24c12009-10-30 11:49:00 +0000472 // Check if this frame is a constructor frame invoked through 'new'.
473 bool IsConstructor() const;
474
475 // Check if this frame has "adapted" arguments in the sense that the
476 // actual passed arguments are available in an arguments adaptor
477 // frame below it on the stack.
478 inline bool has_adapted_arguments() const;
479
480 // Garbage collection support.
481 virtual void Iterate(ObjectVisitor* v) const;
482
483 // Printing support.
484 virtual void Print(StringStream* accumulator,
485 PrintMode mode,
486 int index) const;
487
488 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100489 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000490
Ben Murdochb0fe1622011-05-05 13:52:32 +0100491 // Return a list with JSFunctions of this frame.
492 virtual void GetFunctions(List<JSFunction*>* functions);
493
494 // Build a list with summaries for this frame including all inlined frames.
495 virtual void Summarize(List<FrameSummary>* frames);
496
Steve Blocka7e24c12009-10-30 11:49:00 +0000497 static JavaScriptFrame* cast(StackFrame* frame) {
498 ASSERT(frame->is_java_script());
499 return static_cast<JavaScriptFrame*>(frame);
500 }
501
502 protected:
503 explicit JavaScriptFrame(StackFrameIterator* iterator)
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100504 : StandardFrame(iterator) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000505
506 virtual Address GetCallerStackPointer() const;
507
Ben Murdoch8b112d22011-06-08 16:22:53 +0100508 virtual int GetNumberOfIncomingArguments() const;
509
Ben Murdochb0fe1622011-05-05 13:52:32 +0100510 // Garbage collection support. Iterates over incoming arguments,
511 // receiver, and any callee-saved registers.
512 void IterateArguments(ObjectVisitor* v) const;
513
Steve Blocka7e24c12009-10-30 11:49:00 +0000514 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000515 inline Object* function_slot_object() const;
516
517 friend class StackFrameIterator;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100518 friend class StackTracer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000519};
520
521
Ben Murdochb0fe1622011-05-05 13:52:32 +0100522class OptimizedFrame : public JavaScriptFrame {
523 public:
524 virtual Type type() const { return OPTIMIZED; }
525
526 // GC support.
527 virtual void Iterate(ObjectVisitor* v) const;
528
529 // Return a list with JSFunctions of this frame.
530 // The functions are ordered bottom-to-top (i.e. functions.last()
531 // is the top-most activation)
532 virtual void GetFunctions(List<JSFunction*>* functions);
533
534 virtual void Summarize(List<FrameSummary>* frames);
535
536 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
537
538 protected:
539 explicit OptimizedFrame(StackFrameIterator* iterator)
540 : JavaScriptFrame(iterator) { }
541
542 private:
543 friend class StackFrameIterator;
544};
545
546
Steve Blocka7e24c12009-10-30 11:49:00 +0000547// Arguments adaptor frames are automatically inserted below
548// JavaScript frames when the actual number of parameters does not
549// match the formal number of parameters.
550class ArgumentsAdaptorFrame: public JavaScriptFrame {
551 public:
552 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
553
554 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100555 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000556
557 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
558 ASSERT(frame->is_arguments_adaptor());
559 return static_cast<ArgumentsAdaptorFrame*>(frame);
560 }
561
562 // Printing support.
563 virtual void Print(StringStream* accumulator,
564 PrintMode mode,
565 int index) const;
566 protected:
567 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
568 : JavaScriptFrame(iterator) { }
569
Ben Murdoch8b112d22011-06-08 16:22:53 +0100570 virtual int GetNumberOfIncomingArguments() const {
571 return Smi::cast(GetExpression(0))->value();
572 }
573
Steve Blocka7e24c12009-10-30 11:49:00 +0000574 virtual Address GetCallerStackPointer() const;
575
576 private:
577 friend class StackFrameIterator;
578};
579
580
581class InternalFrame: public StandardFrame {
582 public:
583 virtual Type type() const { return INTERNAL; }
584
585 // Garbage collection support.
586 virtual void Iterate(ObjectVisitor* v) const;
587
588 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100589 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000590
591 static InternalFrame* cast(StackFrame* frame) {
592 ASSERT(frame->is_internal());
593 return static_cast<InternalFrame*>(frame);
594 }
595
596 protected:
597 explicit InternalFrame(StackFrameIterator* iterator)
598 : StandardFrame(iterator) { }
599
600 virtual Address GetCallerStackPointer() const;
601
602 private:
603 friend class StackFrameIterator;
604};
605
606
607// Construct frames are special trampoline frames introduced to handle
608// function invocations through 'new'.
609class ConstructFrame: public InternalFrame {
610 public:
611 virtual Type type() const { return CONSTRUCT; }
612
613 static ConstructFrame* cast(StackFrame* frame) {
614 ASSERT(frame->is_construct());
615 return static_cast<ConstructFrame*>(frame);
616 }
617
618 protected:
619 explicit ConstructFrame(StackFrameIterator* iterator)
620 : InternalFrame(iterator) { }
621
622 private:
623 friend class StackFrameIterator;
624};
625
626
627class StackFrameIterator BASE_EMBEDDED {
628 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100629 // An iterator that iterates over the current thread's stack,
630 // and uses current isolate.
Steve Blocka7e24c12009-10-30 11:49:00 +0000631 StackFrameIterator();
632
Ben Murdoch8b112d22011-06-08 16:22:53 +0100633 // An iterator that iterates over the isolate's current thread's stack,
634 explicit StackFrameIterator(Isolate* isolate);
635
Steve Blocka7e24c12009-10-30 11:49:00 +0000636 // An iterator that iterates over a given thread's stack.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100637 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
Steve Blocka7e24c12009-10-30 11:49:00 +0000638
639 // An iterator that can start from a given FP address.
640 // If use_top, then work as usual, if fp isn't NULL, use it,
641 // otherwise, do nothing.
Steve Block44f0eee2011-05-26 01:26:41 +0100642 StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000643
644 StackFrame* frame() const {
645 ASSERT(!done());
646 return frame_;
647 }
648
Ben Murdoch8b112d22011-06-08 16:22:53 +0100649 Isolate* isolate() const { return isolate_; }
650
Steve Blocka7e24c12009-10-30 11:49:00 +0000651 bool done() const { return frame_ == NULL; }
652 void Advance() { (this->*advance_)(); }
653
654 // Go back to the first frame.
655 void Reset();
656
657 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100658 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000659#define DECLARE_SINGLETON(ignore, type) type type##_;
660 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
661#undef DECLARE_SINGLETON
662 StackFrame* frame_;
663 StackHandler* handler_;
664 ThreadLocalTop* thread_;
665 Address fp_;
666 Address sp_;
667 void (StackFrameIterator::*advance_)();
668
669 StackHandler* handler() const {
670 ASSERT(!done());
671 return handler_;
672 }
673
674 // Get the type-specific frame singleton in a given state.
675 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
676 // A helper function, can return a NULL pointer.
677 StackFrame* SingletonFor(StackFrame::Type type);
678
679 void AdvanceWithHandler();
680 void AdvanceWithoutHandler();
681
682 friend class StackFrame;
683 friend class SafeStackFrameIterator;
684 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
685};
686
687
688// Iterator that supports iterating through all JavaScript frames.
689template<typename Iterator>
690class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
691 public:
692 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
693
Ben Murdoch8b112d22011-06-08 16:22:53 +0100694 inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000695
696 // Skip frames until the frame with the given id is reached.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100697 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
698
699 inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
Steve Blocka7e24c12009-10-30 11:49:00 +0000700
701 JavaScriptFrameIteratorTemp(Address fp, Address sp,
702 Address low_bound, Address high_bound) :
703 iterator_(fp, sp, low_bound, high_bound) {
704 if (!done()) Advance();
705 }
706
Steve Block44f0eee2011-05-26 01:26:41 +0100707 JavaScriptFrameIteratorTemp(Isolate* isolate,
708 Address fp, Address sp,
709 Address low_bound, Address high_bound) :
710 iterator_(isolate, fp, sp, low_bound, high_bound) {
711 if (!done()) Advance();
712 }
713
Steve Blocka7e24c12009-10-30 11:49:00 +0000714 inline JavaScriptFrame* frame() const;
715
716 bool done() const { return iterator_.done(); }
717 void Advance();
718
719 // Advance to the frame holding the arguments for the current
720 // frame. This only affects the current frame if it has adapted
721 // arguments.
722 void AdvanceToArgumentsFrame();
723
724 // Go back to the first frame.
725 void Reset();
726
727 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100728 inline void AdvanceToId(StackFrame::Id id);
729
Steve Blocka7e24c12009-10-30 11:49:00 +0000730 Iterator iterator_;
731};
732
733
734typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
735
736
737// NOTE: The stack trace frame iterator is an iterator that only
738// traverse proper JavaScript frames; that is JavaScript frames that
739// have proper JavaScript functions. This excludes the problematic
740// functions in runtime.js.
741class StackTraceFrameIterator: public JavaScriptFrameIterator {
742 public:
743 StackTraceFrameIterator();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100744 explicit StackTraceFrameIterator(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000745 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000746
747 private:
748 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000749};
750
751
752class SafeStackFrameIterator BASE_EMBEDDED {
753 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100754 SafeStackFrameIterator(Isolate* isolate,
755 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000756 Address low_bound, Address high_bound);
757
758 StackFrame* frame() const {
759 ASSERT(is_working_iterator_);
760 return iterator_.frame();
761 }
762
763 bool done() const { return iteration_done_ ? true : iterator_.done(); }
764
765 void Advance();
766 void Reset();
767
Ben Murdoch8b112d22011-06-08 16:22:53 +0100768 static bool is_active(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100769
Steve Blocka7e24c12009-10-30 11:49:00 +0000770 static bool IsWithinBounds(
771 Address low_bound, Address high_bound, Address addr) {
772 return low_bound <= addr && addr <= high_bound;
773 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000774
775 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100776 class StackAddressValidator {
777 public:
778 StackAddressValidator(Address low_bound, Address high_bound)
779 : low_bound_(low_bound), high_bound_(high_bound) { }
780 bool IsValid(Address addr) const {
781 return IsWithinBounds(low_bound_, high_bound_, addr);
782 }
783 private:
784 Address low_bound_;
785 Address high_bound_;
786 };
787
788 class ExitFrameValidator {
789 public:
790 explicit ExitFrameValidator(const StackAddressValidator& validator)
791 : validator_(validator) { }
792 ExitFrameValidator(Address low_bound, Address high_bound)
793 : validator_(low_bound, high_bound) { }
794 bool IsValidFP(Address fp);
795 private:
796 StackAddressValidator validator_;
797 };
798
Steve Blocka7e24c12009-10-30 11:49:00 +0000799 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100800 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000801 }
802 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
803 bool IsValidFrame(StackFrame* frame) const;
804 bool IsValidCaller(StackFrame* frame);
Steve Block44f0eee2011-05-26 01:26:41 +0100805 static bool IsValidTop(Isolate* isolate,
806 Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000807
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100808 // This is a nasty hack to make sure the active count is incremented
809 // before the constructor for the embedded iterator is invoked. This
810 // is needed because the constructor will start looking at frames
811 // right away and we need to make sure it doesn't start inspecting
812 // heap objects.
813 class ActiveCountMaintainer BASE_EMBEDDED {
814 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100815 explicit ActiveCountMaintainer(Isolate* isolate);
816 ~ActiveCountMaintainer();
817 private:
818 Isolate* isolate_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100819 };
820
821 ActiveCountMaintainer maintainer_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100822 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000823 const bool is_valid_top_;
824 const bool is_valid_fp_;
825 const bool is_working_iterator_;
826 bool iteration_done_;
827 StackFrameIterator iterator_;
828};
829
830
831#ifdef ENABLE_LOGGING_AND_PROFILING
832typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
833 SafeJavaScriptFrameIterator;
834
835
836class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
837 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100838 explicit SafeStackTraceFrameIterator(Isolate* isolate,
839 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000840 Address low_bound, Address high_bound);
841 void Advance();
842};
843#endif
844
845
846class StackFrameLocator BASE_EMBEDDED {
847 public:
848 // Find the nth JavaScript frame on the stack. The caller must
849 // guarantee that such a frame exists.
850 JavaScriptFrame* FindJavaScriptFrame(int n);
851
852 private:
853 StackFrameIterator iterator_;
854};
855
856
Steve Block6ded16b2010-05-10 14:33:55 +0100857// Reads all frames on the current stack and copies them into the current
858// zone memory.
859Vector<StackFrame*> CreateStackMap();
860
Steve Blocka7e24c12009-10-30 11:49:00 +0000861} } // namespace v8::internal
862
863#endif // V8_FRAMES_H_