blob: aa91026fbe44d4c497c81b74390694f72a53e406 [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;
386
Steve Block6ded16b2010-05-10 14:33:55 +0100387 virtual void SetCallerFp(Address caller_fp);
388
Steve Blocka7e24c12009-10-30 11:49:00 +0000389 static StandardFrame* cast(StackFrame* frame) {
390 ASSERT(frame->is_standard());
391 return static_cast<StandardFrame*>(frame);
392 }
393
394 protected:
395 explicit StandardFrame(StackFrameIterator* iterator)
396 : StackFrame(iterator) { }
397
398 virtual void ComputeCallerState(State* state) const;
399
400 // Accessors.
401 inline Address caller_fp() const;
402 inline Address caller_pc() const;
403
404 // Computes the address of the PC field in the standard frame given
405 // by the provided frame pointer.
406 static inline Address ComputePCAddress(Address fp);
407
408 // Iterate over expression stack including stack handlers, locals,
409 // and parts of the fixed part including context and code fields.
410 void IterateExpressions(ObjectVisitor* v) const;
411
412 // Returns the address of the n'th expression stack element.
413 Address GetExpressionAddress(int n) const;
414
415 // Determines if the n'th expression stack element is in a stack
416 // handler or not. Requires traversing all handlers in this frame.
417 bool IsExpressionInsideHandler(int n) const;
418
419 // Determines if the standard frame for the given frame pointer is
420 // an arguments adaptor frame.
421 static inline bool IsArgumentsAdaptorFrame(Address fp);
422
423 // Determines if the standard frame for the given frame pointer is a
424 // construct frame.
425 static inline bool IsConstructFrame(Address fp);
426
427 private:
428 friend class StackFrame;
Kristian Monsen25f61362010-05-21 11:50:48 +0100429 friend class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000430};
431
432
Ben Murdochb0fe1622011-05-05 13:52:32 +0100433class FrameSummary BASE_EMBEDDED {
434 public:
435 FrameSummary(Object* receiver,
436 JSFunction* function,
437 Code* code,
438 int offset,
439 bool is_constructor)
440 : receiver_(receiver),
441 function_(function),
442 code_(code),
443 offset_(offset),
444 is_constructor_(is_constructor) { }
445 Handle<Object> receiver() { return receiver_; }
446 Handle<JSFunction> function() { return function_; }
447 Handle<Code> code() { return code_; }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100448 Address pc() { return code_->address() + offset_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100449 int offset() { return offset_; }
450 bool is_constructor() { return is_constructor_; }
451
452 void Print();
453
454 private:
455 Handle<Object> receiver_;
456 Handle<JSFunction> function_;
457 Handle<Code> code_;
458 int offset_;
459 bool is_constructor_;
460};
461
462
Steve Blocka7e24c12009-10-30 11:49:00 +0000463class JavaScriptFrame: public StandardFrame {
464 public:
465 virtual Type type() const { return JAVA_SCRIPT; }
466
467 // Accessors.
468 inline Object* function() const;
469 inline Object* receiver() const;
470 inline void set_receiver(Object* value);
471
472 // Access the parameters.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100473 inline Address GetParameterSlot(int index) const;
474 inline Object* GetParameter(int index) const;
475 inline int ComputeParametersCount() const {
476 return GetNumberOfIncomingArguments();
477 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000478
Steve Blocka7e24c12009-10-30 11:49:00 +0000479 // Check if this frame is a constructor frame invoked through 'new'.
480 bool IsConstructor() const;
481
482 // Check if this frame has "adapted" arguments in the sense that the
483 // actual passed arguments are available in an arguments adaptor
484 // frame below it on the stack.
485 inline bool has_adapted_arguments() const;
486
487 // Garbage collection support.
488 virtual void Iterate(ObjectVisitor* v) const;
489
490 // Printing support.
491 virtual void Print(StringStream* accumulator,
492 PrintMode mode,
493 int index) const;
494
495 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100496 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000497
Ben Murdochb0fe1622011-05-05 13:52:32 +0100498 // Return a list with JSFunctions of this frame.
499 virtual void GetFunctions(List<JSFunction*>* functions);
500
501 // Build a list with summaries for this frame including all inlined frames.
502 virtual void Summarize(List<FrameSummary>* frames);
503
Steve Blocka7e24c12009-10-30 11:49:00 +0000504 static JavaScriptFrame* cast(StackFrame* frame) {
505 ASSERT(frame->is_java_script());
506 return static_cast<JavaScriptFrame*>(frame);
507 }
508
509 protected:
510 explicit JavaScriptFrame(StackFrameIterator* iterator)
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100511 : StandardFrame(iterator) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000512
513 virtual Address GetCallerStackPointer() const;
514
Ben Murdoch8b112d22011-06-08 16:22:53 +0100515 virtual int GetNumberOfIncomingArguments() const;
516
Ben Murdochb0fe1622011-05-05 13:52:32 +0100517 // Garbage collection support. Iterates over incoming arguments,
518 // receiver, and any callee-saved registers.
519 void IterateArguments(ObjectVisitor* v) const;
520
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000522 inline Object* function_slot_object() const;
523
524 friend class StackFrameIterator;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100525 friend class StackTracer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000526};
527
528
Ben Murdochb0fe1622011-05-05 13:52:32 +0100529class OptimizedFrame : public JavaScriptFrame {
530 public:
531 virtual Type type() const { return OPTIMIZED; }
532
533 // GC support.
534 virtual void Iterate(ObjectVisitor* v) const;
535
536 // Return a list with JSFunctions of this frame.
537 // The functions are ordered bottom-to-top (i.e. functions.last()
538 // is the top-most activation)
539 virtual void GetFunctions(List<JSFunction*>* functions);
540
541 virtual void Summarize(List<FrameSummary>* frames);
542
543 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
544
545 protected:
546 explicit OptimizedFrame(StackFrameIterator* iterator)
547 : JavaScriptFrame(iterator) { }
548
549 private:
550 friend class StackFrameIterator;
551};
552
553
Steve Blocka7e24c12009-10-30 11:49:00 +0000554// Arguments adaptor frames are automatically inserted below
555// JavaScript frames when the actual number of parameters does not
556// match the formal number of parameters.
557class ArgumentsAdaptorFrame: public JavaScriptFrame {
558 public:
559 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
560
561 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100562 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000563
564 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
565 ASSERT(frame->is_arguments_adaptor());
566 return static_cast<ArgumentsAdaptorFrame*>(frame);
567 }
568
569 // Printing support.
570 virtual void Print(StringStream* accumulator,
571 PrintMode mode,
572 int index) const;
573 protected:
574 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
575 : JavaScriptFrame(iterator) { }
576
Ben Murdoch8b112d22011-06-08 16:22:53 +0100577 virtual int GetNumberOfIncomingArguments() const {
578 return Smi::cast(GetExpression(0))->value();
579 }
580
Steve Blocka7e24c12009-10-30 11:49:00 +0000581 virtual Address GetCallerStackPointer() const;
582
583 private:
584 friend class StackFrameIterator;
585};
586
587
588class InternalFrame: public StandardFrame {
589 public:
590 virtual Type type() const { return INTERNAL; }
591
592 // Garbage collection support.
593 virtual void Iterate(ObjectVisitor* v) const;
594
595 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100596 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000597
598 static InternalFrame* cast(StackFrame* frame) {
599 ASSERT(frame->is_internal());
600 return static_cast<InternalFrame*>(frame);
601 }
602
603 protected:
604 explicit InternalFrame(StackFrameIterator* iterator)
605 : StandardFrame(iterator) { }
606
607 virtual Address GetCallerStackPointer() const;
608
609 private:
610 friend class StackFrameIterator;
611};
612
613
614// Construct frames are special trampoline frames introduced to handle
615// function invocations through 'new'.
616class ConstructFrame: public InternalFrame {
617 public:
618 virtual Type type() const { return CONSTRUCT; }
619
620 static ConstructFrame* cast(StackFrame* frame) {
621 ASSERT(frame->is_construct());
622 return static_cast<ConstructFrame*>(frame);
623 }
624
625 protected:
626 explicit ConstructFrame(StackFrameIterator* iterator)
627 : InternalFrame(iterator) { }
628
629 private:
630 friend class StackFrameIterator;
631};
632
633
634class StackFrameIterator BASE_EMBEDDED {
635 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100636 // An iterator that iterates over the current thread's stack,
637 // and uses current isolate.
Steve Blocka7e24c12009-10-30 11:49:00 +0000638 StackFrameIterator();
639
Ben Murdoch8b112d22011-06-08 16:22:53 +0100640 // An iterator that iterates over the isolate's current thread's stack,
641 explicit StackFrameIterator(Isolate* isolate);
642
Steve Blocka7e24c12009-10-30 11:49:00 +0000643 // An iterator that iterates over a given thread's stack.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100644 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
Steve Blocka7e24c12009-10-30 11:49:00 +0000645
646 // An iterator that can start from a given FP address.
647 // If use_top, then work as usual, if fp isn't NULL, use it,
648 // otherwise, do nothing.
Steve Block44f0eee2011-05-26 01:26:41 +0100649 StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000650
651 StackFrame* frame() const {
652 ASSERT(!done());
653 return frame_;
654 }
655
Ben Murdoch8b112d22011-06-08 16:22:53 +0100656 Isolate* isolate() const { return isolate_; }
657
Steve Blocka7e24c12009-10-30 11:49:00 +0000658 bool done() const { return frame_ == NULL; }
659 void Advance() { (this->*advance_)(); }
660
661 // Go back to the first frame.
662 void Reset();
663
664 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100665 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000666#define DECLARE_SINGLETON(ignore, type) type type##_;
667 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
668#undef DECLARE_SINGLETON
669 StackFrame* frame_;
670 StackHandler* handler_;
671 ThreadLocalTop* thread_;
672 Address fp_;
673 Address sp_;
674 void (StackFrameIterator::*advance_)();
675
676 StackHandler* handler() const {
677 ASSERT(!done());
678 return handler_;
679 }
680
681 // Get the type-specific frame singleton in a given state.
682 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
683 // A helper function, can return a NULL pointer.
684 StackFrame* SingletonFor(StackFrame::Type type);
685
686 void AdvanceWithHandler();
687 void AdvanceWithoutHandler();
688
689 friend class StackFrame;
690 friend class SafeStackFrameIterator;
691 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
692};
693
694
695// Iterator that supports iterating through all JavaScript frames.
696template<typename Iterator>
697class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
698 public:
699 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
700
Ben Murdoch8b112d22011-06-08 16:22:53 +0100701 inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000702
703 // Skip frames until the frame with the given id is reached.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100704 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
705
706 inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
Steve Blocka7e24c12009-10-30 11:49:00 +0000707
708 JavaScriptFrameIteratorTemp(Address fp, Address sp,
709 Address low_bound, Address high_bound) :
710 iterator_(fp, sp, low_bound, high_bound) {
711 if (!done()) Advance();
712 }
713
Steve Block44f0eee2011-05-26 01:26:41 +0100714 JavaScriptFrameIteratorTemp(Isolate* isolate,
715 Address fp, Address sp,
716 Address low_bound, Address high_bound) :
717 iterator_(isolate, fp, sp, low_bound, high_bound) {
718 if (!done()) Advance();
719 }
720
Steve Blocka7e24c12009-10-30 11:49:00 +0000721 inline JavaScriptFrame* frame() const;
722
723 bool done() const { return iterator_.done(); }
724 void Advance();
725
726 // Advance to the frame holding the arguments for the current
727 // frame. This only affects the current frame if it has adapted
728 // arguments.
729 void AdvanceToArgumentsFrame();
730
731 // Go back to the first frame.
732 void Reset();
733
734 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100735 inline void AdvanceToId(StackFrame::Id id);
736
Steve Blocka7e24c12009-10-30 11:49:00 +0000737 Iterator iterator_;
738};
739
740
741typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
742
743
744// NOTE: The stack trace frame iterator is an iterator that only
745// traverse proper JavaScript frames; that is JavaScript frames that
746// have proper JavaScript functions. This excludes the problematic
747// functions in runtime.js.
748class StackTraceFrameIterator: public JavaScriptFrameIterator {
749 public:
750 StackTraceFrameIterator();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100751 explicit StackTraceFrameIterator(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000752 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000753
754 private:
755 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000756};
757
758
759class SafeStackFrameIterator BASE_EMBEDDED {
760 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100761 SafeStackFrameIterator(Isolate* isolate,
762 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000763 Address low_bound, Address high_bound);
764
765 StackFrame* frame() const {
766 ASSERT(is_working_iterator_);
767 return iterator_.frame();
768 }
769
770 bool done() const { return iteration_done_ ? true : iterator_.done(); }
771
772 void Advance();
773 void Reset();
774
Ben Murdoch8b112d22011-06-08 16:22:53 +0100775 static bool is_active(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100776
Steve Blocka7e24c12009-10-30 11:49:00 +0000777 static bool IsWithinBounds(
778 Address low_bound, Address high_bound, Address addr) {
779 return low_bound <= addr && addr <= high_bound;
780 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000781
782 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100783 class StackAddressValidator {
784 public:
785 StackAddressValidator(Address low_bound, Address high_bound)
786 : low_bound_(low_bound), high_bound_(high_bound) { }
787 bool IsValid(Address addr) const {
788 return IsWithinBounds(low_bound_, high_bound_, addr);
789 }
790 private:
791 Address low_bound_;
792 Address high_bound_;
793 };
794
795 class ExitFrameValidator {
796 public:
797 explicit ExitFrameValidator(const StackAddressValidator& validator)
798 : validator_(validator) { }
799 ExitFrameValidator(Address low_bound, Address high_bound)
800 : validator_(low_bound, high_bound) { }
801 bool IsValidFP(Address fp);
802 private:
803 StackAddressValidator validator_;
804 };
805
Steve Blocka7e24c12009-10-30 11:49:00 +0000806 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100807 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000808 }
809 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
810 bool IsValidFrame(StackFrame* frame) const;
811 bool IsValidCaller(StackFrame* frame);
Steve Block44f0eee2011-05-26 01:26:41 +0100812 static bool IsValidTop(Isolate* isolate,
813 Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000814
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100815 // This is a nasty hack to make sure the active count is incremented
816 // before the constructor for the embedded iterator is invoked. This
817 // is needed because the constructor will start looking at frames
818 // right away and we need to make sure it doesn't start inspecting
819 // heap objects.
820 class ActiveCountMaintainer BASE_EMBEDDED {
821 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100822 explicit ActiveCountMaintainer(Isolate* isolate);
823 ~ActiveCountMaintainer();
824 private:
825 Isolate* isolate_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100826 };
827
828 ActiveCountMaintainer maintainer_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100829 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000830 const bool is_valid_top_;
831 const bool is_valid_fp_;
832 const bool is_working_iterator_;
833 bool iteration_done_;
834 StackFrameIterator iterator_;
835};
836
837
838#ifdef ENABLE_LOGGING_AND_PROFILING
839typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
840 SafeJavaScriptFrameIterator;
841
842
843class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
844 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100845 explicit SafeStackTraceFrameIterator(Isolate* isolate,
846 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000847 Address low_bound, Address high_bound);
848 void Advance();
849};
850#endif
851
852
853class StackFrameLocator BASE_EMBEDDED {
854 public:
855 // Find the nth JavaScript frame on the stack. The caller must
856 // guarantee that such a frame exists.
857 JavaScriptFrame* FindJavaScriptFrame(int n);
858
859 private:
860 StackFrameIterator iterator_;
861};
862
863
Steve Block6ded16b2010-05-10 14:33:55 +0100864// Reads all frames on the current stack and copies them into the current
865// zone memory.
866Vector<StackFrame*> CreateStackMap();
867
Steve Blocka7e24c12009-10-30 11:49:00 +0000868} } // namespace v8::internal
869
870#endif // V8_FRAMES_H_