blob: 6fe6a637a97426fbd05577811453397b98a6480b [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
Steve Block053d10c2011-06-13 19:13:29 +0100154 // Used to mark the outermost JS entry frame.
155 enum JsFrameMarker {
156 INNER_JSENTRY_FRAME = 0,
157 OUTERMOST_JSENTRY_FRAME = 1
158 };
159
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100160 struct State {
161 State() : sp(NULL), fp(NULL), pc_address(NULL) { }
162 Address sp;
163 Address fp;
164 Address* pc_address;
165 };
166
Ben Murdoch8b112d22011-06-08 16:22:53 +0100167 // Copy constructor; it breaks the connection to host iterator
168 // (as an iterator usually lives on stack).
Steve Block6ded16b2010-05-10 14:33:55 +0100169 StackFrame(const StackFrame& original) {
170 this->state_ = original.state_;
171 this->iterator_ = NULL;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100172 this->isolate_ = original.isolate_;
Steve Block6ded16b2010-05-10 14:33:55 +0100173 }
174
Steve Blocka7e24c12009-10-30 11:49:00 +0000175 // Type testers.
176 bool is_entry() const { return type() == ENTRY; }
177 bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
178 bool is_exit() const { return type() == EXIT; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100179 bool is_optimized() const { return type() == OPTIMIZED; }
Steve Blocka7e24c12009-10-30 11:49:00 +0000180 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
181 bool is_internal() const { return type() == INTERNAL; }
182 bool is_construct() const { return type() == CONSTRUCT; }
183 virtual bool is_standard() const { return false; }
184
Ben Murdochb0fe1622011-05-05 13:52:32 +0100185 bool is_java_script() const {
186 Type type = this->type();
187 return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
188 }
189
Steve Blocka7e24c12009-10-30 11:49:00 +0000190 // Accessors.
191 Address sp() const { return state_.sp; }
192 Address fp() const { return state_.fp; }
193 Address caller_sp() const { return GetCallerStackPointer(); }
194
195 Address pc() const { return *pc_address(); }
196 void set_pc(Address pc) { *pc_address() = pc; }
197
Steve Block6ded16b2010-05-10 14:33:55 +0100198 virtual void SetCallerFp(Address caller_fp) = 0;
199
Steve Blocka7e24c12009-10-30 11:49:00 +0000200 Address* pc_address() const { return state_.pc_address; }
201
202 // Get the id of this stack frame.
203 Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
204
205 // Checks if this frame includes any stack handlers.
206 bool HasHandler() const;
207
208 // Get the type of this frame.
209 virtual Type type() const = 0;
210
211 // Get the code associated with this frame.
Iain Merrick75681382010-08-19 15:07:18 +0100212 // This method could be called during marking phase of GC.
213 virtual Code* unchecked_code() const = 0;
214
215 // Get the code associated with this frame.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100216 Code* LookupCode() const {
217 return GetContainingCode(isolate(), pc());
Steve Block44f0eee2011-05-26 01:26:41 +0100218 }
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100219
220 // Get the code object that contains the given pc.
Steve Block44f0eee2011-05-26 01:26:41 +0100221 static inline Code* GetContainingCode(Isolate* isolate, Address pc);
Steve Blocka7e24c12009-10-30 11:49:00 +0000222
Ben Murdochb0fe1622011-05-05 13:52:32 +0100223 // Get the code object containing the given pc and fill in the
224 // safepoint entry and the number of stack slots. The pc must be at
225 // a safepoint.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100226 static Code* GetSafepointData(Isolate* isolate,
227 Address pc,
Ben Murdochb8e0da22011-05-16 14:20:40 +0100228 SafepointEntry* safepoint_entry,
Ben Murdochb0fe1622011-05-05 13:52:32 +0100229 unsigned* stack_slots);
230
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100231 virtual void Iterate(ObjectVisitor* v) const = 0;
232 static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
Steve Blocka7e24c12009-10-30 11:49:00 +0000233
Steve Blocka7e24c12009-10-30 11:49:00 +0000234
235 // Printing support.
236 enum PrintMode { OVERVIEW, DETAILS };
237 virtual void Print(StringStream* accumulator,
238 PrintMode mode,
239 int index) const { }
240
241 protected:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100242 inline explicit StackFrame(StackFrameIterator* iterator);
Steve Blocka7e24c12009-10-30 11:49:00 +0000243 virtual ~StackFrame() { }
244
Ben Murdoch8b112d22011-06-08 16:22:53 +0100245 Isolate* isolate() const { return isolate_; }
246
Steve Blocka7e24c12009-10-30 11:49:00 +0000247 // Compute the stack pointer for the calling frame.
248 virtual Address GetCallerStackPointer() const = 0;
249
250 // Printing support.
251 static void PrintIndex(StringStream* accumulator,
252 PrintMode mode,
253 int index);
254
255 // Get the top handler from the current stack iterator.
256 inline StackHandler* top_handler() const;
257
258 // Compute the stack frame type for the given state.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100259 static Type ComputeType(Isolate* isolate, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000260
261 private:
262 const StackFrameIterator* iterator_;
Ben Murdoch8b112d22011-06-08 16:22:53 +0100263 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000264 State state_;
265
266 // Fill in the state of the calling frame.
267 virtual void ComputeCallerState(State* state) const = 0;
268
269 // Get the type and the state of the calling frame.
270 virtual Type GetCallerState(State* state) const;
271
Ben Murdoch8b112d22011-06-08 16:22:53 +0100272 static const intptr_t kIsolateTag = 1;
273
Steve Blocka7e24c12009-10-30 11:49:00 +0000274 friend class StackFrameIterator;
275 friend class StackHandlerIterator;
276 friend class SafeStackFrameIterator;
277
Steve Block6ded16b2010-05-10 14:33:55 +0100278 private:
279 void operator=(const StackFrame& original);
Steve Blocka7e24c12009-10-30 11:49:00 +0000280};
281
282
283// Entry frames are used to enter JavaScript execution from C.
284class EntryFrame: public StackFrame {
285 public:
286 virtual Type type() const { return ENTRY; }
287
Iain Merrick75681382010-08-19 15:07:18 +0100288 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000289
290 // Garbage collection support.
291 virtual void Iterate(ObjectVisitor* v) const;
292
293 static EntryFrame* cast(StackFrame* frame) {
294 ASSERT(frame->is_entry());
295 return static_cast<EntryFrame*>(frame);
296 }
Steve Block6ded16b2010-05-10 14:33:55 +0100297 virtual void SetCallerFp(Address caller_fp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000298
299 protected:
300 explicit EntryFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
301
302 // The caller stack pointer for entry frames is always zero. The
303 // real information about the caller frame is available through the
304 // link to the top exit frame.
305 virtual Address GetCallerStackPointer() const { return 0; }
306
307 private:
308 virtual void ComputeCallerState(State* state) const;
309 virtual Type GetCallerState(State* state) const;
310
311 friend class StackFrameIterator;
312};
313
314
315class EntryConstructFrame: public EntryFrame {
316 public:
317 virtual Type type() const { return ENTRY_CONSTRUCT; }
318
Iain Merrick75681382010-08-19 15:07:18 +0100319 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000320
321 static EntryConstructFrame* cast(StackFrame* frame) {
322 ASSERT(frame->is_entry_construct());
323 return static_cast<EntryConstructFrame*>(frame);
324 }
325
326 protected:
327 explicit EntryConstructFrame(StackFrameIterator* iterator)
328 : EntryFrame(iterator) { }
329
330 private:
331 friend class StackFrameIterator;
332};
333
334
335// Exit frames are used to exit JavaScript execution and go to C.
336class ExitFrame: public StackFrame {
337 public:
338 virtual Type type() const { return EXIT; }
339
Iain Merrick75681382010-08-19 15:07:18 +0100340 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000341
Steve Blockd0582a62009-12-15 09:54:21 +0000342 Object*& code_slot() const;
343
Steve Blocka7e24c12009-10-30 11:49:00 +0000344 // Garbage collection support.
345 virtual void Iterate(ObjectVisitor* v) const;
346
Steve Block6ded16b2010-05-10 14:33:55 +0100347 virtual void SetCallerFp(Address caller_fp);
348
Steve Blocka7e24c12009-10-30 11:49:00 +0000349 static ExitFrame* cast(StackFrame* frame) {
350 ASSERT(frame->is_exit());
351 return static_cast<ExitFrame*>(frame);
352 }
353
354 // Compute the state and type of an exit frame given a frame
355 // pointer. Used when constructing the first stack frame seen by an
356 // iterator and the frames following entry frames.
357 static Type GetStateForFramePointer(Address fp, State* state);
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100358 static Address ComputeStackPointer(Address fp);
359 static void FillState(Address fp, Address sp, State* state);
Steve Blocka7e24c12009-10-30 11:49:00 +0000360
361 protected:
362 explicit ExitFrame(StackFrameIterator* iterator) : StackFrame(iterator) { }
363
364 virtual Address GetCallerStackPointer() const;
365
366 private:
367 virtual void ComputeCallerState(State* state) const;
368
369 friend class StackFrameIterator;
370};
371
372
Steve Blocka7e24c12009-10-30 11:49:00 +0000373class StandardFrame: public StackFrame {
374 public:
375 // Testers.
376 virtual bool is_standard() const { return true; }
377
378 // Accessors.
379 inline Object* context() const;
380
381 // Access the expressions in the stack frame including locals.
382 inline Object* GetExpression(int index) const;
383 inline void SetExpression(int index, Object* value);
384 int ComputeExpressionsCount() const;
385
Steve Block6ded16b2010-05-10 14:33:55 +0100386 virtual void SetCallerFp(Address caller_fp);
387
Steve Blocka7e24c12009-10-30 11:49:00 +0000388 static StandardFrame* cast(StackFrame* frame) {
389 ASSERT(frame->is_standard());
390 return static_cast<StandardFrame*>(frame);
391 }
392
393 protected:
394 explicit StandardFrame(StackFrameIterator* iterator)
395 : StackFrame(iterator) { }
396
397 virtual void ComputeCallerState(State* state) const;
398
399 // Accessors.
400 inline Address caller_fp() const;
401 inline Address caller_pc() const;
402
403 // Computes the address of the PC field in the standard frame given
404 // by the provided frame pointer.
405 static inline Address ComputePCAddress(Address fp);
406
407 // Iterate over expression stack including stack handlers, locals,
408 // and parts of the fixed part including context and code fields.
409 void IterateExpressions(ObjectVisitor* v) const;
410
411 // Returns the address of the n'th expression stack element.
412 Address GetExpressionAddress(int n) const;
413
414 // Determines if the n'th expression stack element is in a stack
415 // handler or not. Requires traversing all handlers in this frame.
416 bool IsExpressionInsideHandler(int n) const;
417
418 // Determines if the standard frame for the given frame pointer is
419 // an arguments adaptor frame.
420 static inline bool IsArgumentsAdaptorFrame(Address fp);
421
422 // Determines if the standard frame for the given frame pointer is a
423 // construct frame.
424 static inline bool IsConstructFrame(Address fp);
425
426 private:
427 friend class StackFrame;
Kristian Monsen25f61362010-05-21 11:50:48 +0100428 friend class StackFrameIterator;
Steve Blocka7e24c12009-10-30 11:49:00 +0000429};
430
431
Ben Murdochb0fe1622011-05-05 13:52:32 +0100432class FrameSummary BASE_EMBEDDED {
433 public:
434 FrameSummary(Object* receiver,
435 JSFunction* function,
436 Code* code,
437 int offset,
438 bool is_constructor)
439 : receiver_(receiver),
440 function_(function),
441 code_(code),
442 offset_(offset),
443 is_constructor_(is_constructor) { }
444 Handle<Object> receiver() { return receiver_; }
445 Handle<JSFunction> function() { return function_; }
446 Handle<Code> code() { return code_; }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100447 Address pc() { return code_->address() + offset_; }
Ben Murdochb0fe1622011-05-05 13:52:32 +0100448 int offset() { return offset_; }
449 bool is_constructor() { return is_constructor_; }
450
451 void Print();
452
453 private:
454 Handle<Object> receiver_;
455 Handle<JSFunction> function_;
456 Handle<Code> code_;
457 int offset_;
458 bool is_constructor_;
459};
460
461
Steve Blocka7e24c12009-10-30 11:49:00 +0000462class JavaScriptFrame: public StandardFrame {
463 public:
464 virtual Type type() const { return JAVA_SCRIPT; }
465
466 // Accessors.
467 inline Object* function() const;
468 inline Object* receiver() const;
469 inline void set_receiver(Object* value);
470
471 // Access the parameters.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100472 inline Address GetParameterSlot(int index) const;
473 inline Object* GetParameter(int index) const;
474 inline int ComputeParametersCount() const {
475 return GetNumberOfIncomingArguments();
476 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000477
Steve Blocka7e24c12009-10-30 11:49:00 +0000478 // Check if this frame is a constructor frame invoked through 'new'.
479 bool IsConstructor() const;
480
481 // Check if this frame has "adapted" arguments in the sense that the
482 // actual passed arguments are available in an arguments adaptor
483 // frame below it on the stack.
484 inline bool has_adapted_arguments() const;
485
486 // Garbage collection support.
487 virtual void Iterate(ObjectVisitor* v) const;
488
489 // Printing support.
490 virtual void Print(StringStream* accumulator,
491 PrintMode mode,
492 int index) const;
493
494 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100495 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000496
Ben Murdochb0fe1622011-05-05 13:52:32 +0100497 // Return a list with JSFunctions of this frame.
498 virtual void GetFunctions(List<JSFunction*>* functions);
499
500 // Build a list with summaries for this frame including all inlined frames.
501 virtual void Summarize(List<FrameSummary>* frames);
502
Steve Blocka7e24c12009-10-30 11:49:00 +0000503 static JavaScriptFrame* cast(StackFrame* frame) {
504 ASSERT(frame->is_java_script());
505 return static_cast<JavaScriptFrame*>(frame);
506 }
507
508 protected:
509 explicit JavaScriptFrame(StackFrameIterator* iterator)
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100510 : StandardFrame(iterator) { }
Steve Blocka7e24c12009-10-30 11:49:00 +0000511
512 virtual Address GetCallerStackPointer() const;
513
Ben Murdoch8b112d22011-06-08 16:22:53 +0100514 virtual int GetNumberOfIncomingArguments() const;
515
Ben Murdochb0fe1622011-05-05 13:52:32 +0100516 // Garbage collection support. Iterates over incoming arguments,
517 // receiver, and any callee-saved registers.
518 void IterateArguments(ObjectVisitor* v) const;
519
Steve Blocka7e24c12009-10-30 11:49:00 +0000520 private:
Steve Blocka7e24c12009-10-30 11:49:00 +0000521 inline Object* function_slot_object() const;
522
523 friend class StackFrameIterator;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100524 friend class StackTracer;
Steve Blocka7e24c12009-10-30 11:49:00 +0000525};
526
527
Ben Murdochb0fe1622011-05-05 13:52:32 +0100528class OptimizedFrame : public JavaScriptFrame {
529 public:
530 virtual Type type() const { return OPTIMIZED; }
531
532 // GC support.
533 virtual void Iterate(ObjectVisitor* v) const;
534
535 // Return a list with JSFunctions of this frame.
536 // The functions are ordered bottom-to-top (i.e. functions.last()
537 // is the top-most activation)
538 virtual void GetFunctions(List<JSFunction*>* functions);
539
540 virtual void Summarize(List<FrameSummary>* frames);
541
542 DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
543
544 protected:
545 explicit OptimizedFrame(StackFrameIterator* iterator)
546 : JavaScriptFrame(iterator) { }
547
548 private:
549 friend class StackFrameIterator;
550};
551
552
Steve Blocka7e24c12009-10-30 11:49:00 +0000553// Arguments adaptor frames are automatically inserted below
554// JavaScript frames when the actual number of parameters does not
555// match the formal number of parameters.
556class ArgumentsAdaptorFrame: public JavaScriptFrame {
557 public:
558 virtual Type type() const { return ARGUMENTS_ADAPTOR; }
559
560 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100561 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000562
563 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
564 ASSERT(frame->is_arguments_adaptor());
565 return static_cast<ArgumentsAdaptorFrame*>(frame);
566 }
567
568 // Printing support.
569 virtual void Print(StringStream* accumulator,
570 PrintMode mode,
571 int index) const;
572 protected:
573 explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator)
574 : JavaScriptFrame(iterator) { }
575
Ben Murdoch8b112d22011-06-08 16:22:53 +0100576 virtual int GetNumberOfIncomingArguments() const {
577 return Smi::cast(GetExpression(0))->value();
578 }
579
Steve Blocka7e24c12009-10-30 11:49:00 +0000580 virtual Address GetCallerStackPointer() const;
581
582 private:
583 friend class StackFrameIterator;
584};
585
586
587class InternalFrame: public StandardFrame {
588 public:
589 virtual Type type() const { return INTERNAL; }
590
591 // Garbage collection support.
592 virtual void Iterate(ObjectVisitor* v) const;
593
594 // Determine the code for the frame.
Iain Merrick75681382010-08-19 15:07:18 +0100595 virtual Code* unchecked_code() const;
Steve Blocka7e24c12009-10-30 11:49:00 +0000596
597 static InternalFrame* cast(StackFrame* frame) {
598 ASSERT(frame->is_internal());
599 return static_cast<InternalFrame*>(frame);
600 }
601
602 protected:
603 explicit InternalFrame(StackFrameIterator* iterator)
604 : StandardFrame(iterator) { }
605
606 virtual Address GetCallerStackPointer() const;
607
608 private:
609 friend class StackFrameIterator;
610};
611
612
613// Construct frames are special trampoline frames introduced to handle
614// function invocations through 'new'.
615class ConstructFrame: public InternalFrame {
616 public:
617 virtual Type type() const { return CONSTRUCT; }
618
619 static ConstructFrame* cast(StackFrame* frame) {
620 ASSERT(frame->is_construct());
621 return static_cast<ConstructFrame*>(frame);
622 }
623
624 protected:
625 explicit ConstructFrame(StackFrameIterator* iterator)
626 : InternalFrame(iterator) { }
627
628 private:
629 friend class StackFrameIterator;
630};
631
632
633class StackFrameIterator BASE_EMBEDDED {
634 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100635 // An iterator that iterates over the current thread's stack,
636 // and uses current isolate.
Steve Blocka7e24c12009-10-30 11:49:00 +0000637 StackFrameIterator();
638
Ben Murdoch8b112d22011-06-08 16:22:53 +0100639 // An iterator that iterates over the isolate's current thread's stack,
640 explicit StackFrameIterator(Isolate* isolate);
641
Steve Blocka7e24c12009-10-30 11:49:00 +0000642 // An iterator that iterates over a given thread's stack.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100643 StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
Steve Blocka7e24c12009-10-30 11:49:00 +0000644
645 // An iterator that can start from a given FP address.
646 // If use_top, then work as usual, if fp isn't NULL, use it,
647 // otherwise, do nothing.
Steve Block44f0eee2011-05-26 01:26:41 +0100648 StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
Steve Blocka7e24c12009-10-30 11:49:00 +0000649
650 StackFrame* frame() const {
651 ASSERT(!done());
652 return frame_;
653 }
654
Ben Murdoch8b112d22011-06-08 16:22:53 +0100655 Isolate* isolate() const { return isolate_; }
656
Steve Blocka7e24c12009-10-30 11:49:00 +0000657 bool done() const { return frame_ == NULL; }
658 void Advance() { (this->*advance_)(); }
659
660 // Go back to the first frame.
661 void Reset();
662
663 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100664 Isolate* isolate_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000665#define DECLARE_SINGLETON(ignore, type) type type##_;
666 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
667#undef DECLARE_SINGLETON
668 StackFrame* frame_;
669 StackHandler* handler_;
670 ThreadLocalTop* thread_;
671 Address fp_;
672 Address sp_;
673 void (StackFrameIterator::*advance_)();
674
675 StackHandler* handler() const {
676 ASSERT(!done());
677 return handler_;
678 }
679
680 // Get the type-specific frame singleton in a given state.
681 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
682 // A helper function, can return a NULL pointer.
683 StackFrame* SingletonFor(StackFrame::Type type);
684
685 void AdvanceWithHandler();
686 void AdvanceWithoutHandler();
687
688 friend class StackFrame;
689 friend class SafeStackFrameIterator;
690 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
691};
692
693
694// Iterator that supports iterating through all JavaScript frames.
695template<typename Iterator>
696class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
697 public:
698 JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
699
Ben Murdoch8b112d22011-06-08 16:22:53 +0100700 inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000701
702 // Skip frames until the frame with the given id is reached.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100703 explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
704
705 inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
Steve Blocka7e24c12009-10-30 11:49:00 +0000706
707 JavaScriptFrameIteratorTemp(Address fp, Address sp,
708 Address low_bound, Address high_bound) :
709 iterator_(fp, sp, low_bound, high_bound) {
710 if (!done()) Advance();
711 }
712
Steve Block44f0eee2011-05-26 01:26:41 +0100713 JavaScriptFrameIteratorTemp(Isolate* isolate,
714 Address fp, Address sp,
715 Address low_bound, Address high_bound) :
716 iterator_(isolate, fp, sp, low_bound, high_bound) {
717 if (!done()) Advance();
718 }
719
Steve Blocka7e24c12009-10-30 11:49:00 +0000720 inline JavaScriptFrame* frame() const;
721
722 bool done() const { return iterator_.done(); }
723 void Advance();
724
725 // Advance to the frame holding the arguments for the current
726 // frame. This only affects the current frame if it has adapted
727 // arguments.
728 void AdvanceToArgumentsFrame();
729
730 // Go back to the first frame.
731 void Reset();
732
733 private:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100734 inline void AdvanceToId(StackFrame::Id id);
735
Steve Blocka7e24c12009-10-30 11:49:00 +0000736 Iterator iterator_;
737};
738
739
740typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
741
742
743// NOTE: The stack trace frame iterator is an iterator that only
744// traverse proper JavaScript frames; that is JavaScript frames that
745// have proper JavaScript functions. This excludes the problematic
746// functions in runtime.js.
747class StackTraceFrameIterator: public JavaScriptFrameIterator {
748 public:
749 StackTraceFrameIterator();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100750 explicit StackTraceFrameIterator(Isolate* isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000751 void Advance();
Leon Clarke4515c472010-02-03 11:58:03 +0000752
753 private:
754 bool IsValidFrame();
Steve Blocka7e24c12009-10-30 11:49:00 +0000755};
756
757
758class SafeStackFrameIterator BASE_EMBEDDED {
759 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100760 SafeStackFrameIterator(Isolate* isolate,
761 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000762 Address low_bound, Address high_bound);
763
764 StackFrame* frame() const {
765 ASSERT(is_working_iterator_);
766 return iterator_.frame();
767 }
768
769 bool done() const { return iteration_done_ ? true : iterator_.done(); }
770
771 void Advance();
772 void Reset();
773
Ben Murdoch8b112d22011-06-08 16:22:53 +0100774 static bool is_active(Isolate* isolate);
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100775
Steve Blocka7e24c12009-10-30 11:49:00 +0000776 static bool IsWithinBounds(
777 Address low_bound, Address high_bound, Address addr) {
778 return low_bound <= addr && addr <= high_bound;
779 }
Leon Clarked91b9f72010-01-27 17:25:45 +0000780
781 private:
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100782 class StackAddressValidator {
783 public:
784 StackAddressValidator(Address low_bound, Address high_bound)
785 : low_bound_(low_bound), high_bound_(high_bound) { }
786 bool IsValid(Address addr) const {
787 return IsWithinBounds(low_bound_, high_bound_, addr);
788 }
789 private:
790 Address low_bound_;
791 Address high_bound_;
792 };
793
794 class ExitFrameValidator {
795 public:
796 explicit ExitFrameValidator(const StackAddressValidator& validator)
797 : validator_(validator) { }
798 ExitFrameValidator(Address low_bound, Address high_bound)
799 : validator_(low_bound, high_bound) { }
800 bool IsValidFP(Address fp);
801 private:
802 StackAddressValidator validator_;
803 };
804
Steve Blocka7e24c12009-10-30 11:49:00 +0000805 bool IsValidStackAddress(Address addr) const {
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100806 return stack_validator_.IsValid(addr);
Steve Blocka7e24c12009-10-30 11:49:00 +0000807 }
808 bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
809 bool IsValidFrame(StackFrame* frame) const;
810 bool IsValidCaller(StackFrame* frame);
Steve Block44f0eee2011-05-26 01:26:41 +0100811 static bool IsValidTop(Isolate* isolate,
812 Address low_bound, Address high_bound);
Steve Blocka7e24c12009-10-30 11:49:00 +0000813
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100814 // This is a nasty hack to make sure the active count is incremented
815 // before the constructor for the embedded iterator is invoked. This
816 // is needed because the constructor will start looking at frames
817 // right away and we need to make sure it doesn't start inspecting
818 // heap objects.
819 class ActiveCountMaintainer BASE_EMBEDDED {
820 public:
Ben Murdoch8b112d22011-06-08 16:22:53 +0100821 explicit ActiveCountMaintainer(Isolate* isolate);
822 ~ActiveCountMaintainer();
823 private:
824 Isolate* isolate_;
Kristian Monsen80d68ea2010-09-08 11:05:35 +0100825 };
826
827 ActiveCountMaintainer maintainer_;
Kristian Monsen0d5e1162010-09-30 15:31:59 +0100828 StackAddressValidator stack_validator_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000829 const bool is_valid_top_;
830 const bool is_valid_fp_;
831 const bool is_working_iterator_;
832 bool iteration_done_;
833 StackFrameIterator iterator_;
834};
835
836
837#ifdef ENABLE_LOGGING_AND_PROFILING
838typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
839 SafeJavaScriptFrameIterator;
840
841
842class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
843 public:
Steve Block44f0eee2011-05-26 01:26:41 +0100844 explicit SafeStackTraceFrameIterator(Isolate* isolate,
845 Address fp, Address sp,
Steve Blocka7e24c12009-10-30 11:49:00 +0000846 Address low_bound, Address high_bound);
847 void Advance();
848};
849#endif
850
851
852class StackFrameLocator BASE_EMBEDDED {
853 public:
854 // Find the nth JavaScript frame on the stack. The caller must
855 // guarantee that such a frame exists.
856 JavaScriptFrame* FindJavaScriptFrame(int n);
857
858 private:
859 StackFrameIterator iterator_;
860};
861
862
Steve Block6ded16b2010-05-10 14:33:55 +0100863// Reads all frames on the current stack and copies them into the current
864// zone memory.
865Vector<StackFrame*> CreateStackMap();
866
Steve Blocka7e24c12009-10-30 11:49:00 +0000867} } // namespace v8::internal
868
869#endif // V8_FRAMES_H_