1
// Copyright 2012 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
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.
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.
31
#include "allocation.h"
33
#include "safepoint-table.h"
38
typedef uint32_t RegList;
40
// Get the number of registers in a given register list.
41
int NumRegs(RegList list);
43
void SetUpJSCallerSavedCodeData();
45
// Return the code of the n-th saved register available to JavaScript.
46
int JSCallerSavedCode(int n);
49
// Forward declarations.
50
class StackFrameIterator;
54
class InnerPointerToCodeCache {
56
struct InnerPointerToCodeCacheEntry {
57
Address inner_pointer;
59
SafepointEntry safepoint_entry;
62
explicit InnerPointerToCodeCache(Isolate* isolate) : isolate_(isolate) {
66
Code* GcSafeFindCodeForInnerPointer(Address inner_pointer);
67
Code* GcSafeCastToCode(HeapObject* object, Address inner_pointer);
70
memset(&cache_[0], 0, sizeof(cache_));
73
InnerPointerToCodeCacheEntry* GetCacheEntry(Address inner_pointer);
76
InnerPointerToCodeCacheEntry* cache(int index) { return &cache_[index]; }
80
static const int kInnerPointerToCodeCacheSize = 1024;
81
InnerPointerToCodeCacheEntry cache_[kInnerPointerToCodeCacheSize];
83
DISALLOW_COPY_AND_ASSIGN(InnerPointerToCodeCache);
87
class StackHandler BASE_EMBEDDED {
96
static const int kKindWidth = 2;
97
STATIC_ASSERT(LAST_KIND < (1 << kKindWidth));
98
static const int kIndexWidth = 32 - kKindWidth;
99
class KindField: public BitField<StackHandler::Kind, 0, kKindWidth> {};
100
class IndexField: public BitField<unsigned, kKindWidth, kIndexWidth> {};
102
// Get the address of this stack handler.
103
inline Address address() const;
105
// Get the next stack handler in the chain.
106
inline StackHandler* next() const;
108
// Tells whether the given address is inside this handler.
109
inline bool includes(Address address) const;
111
// Garbage collection support.
112
inline void Iterate(ObjectVisitor* v, Code* holder) const;
114
// Conversion support.
115
static inline StackHandler* FromAddress(Address address);
118
inline bool is_js_entry() const;
119
inline bool is_catch() const;
120
inline bool is_finally() const;
124
inline Kind kind() const;
126
inline Object** context_address() const;
127
inline Object** code_address() const;
129
DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
133
#define STACK_FRAME_TYPE_LIST(V) \
134
V(ENTRY, EntryFrame) \
135
V(ENTRY_CONSTRUCT, EntryConstructFrame) \
137
V(JAVA_SCRIPT, JavaScriptFrame) \
138
V(OPTIMIZED, OptimizedFrame) \
139
V(INTERNAL, InternalFrame) \
140
V(CONSTRUCT, ConstructFrame) \
141
V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame)
144
// Abstract base class for all stack frames.
145
class StackFrame BASE_EMBEDDED {
147
#define DECLARE_TYPE(type, ignore) type,
150
STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
152
// Used by FrameScope to indicate that the stack frame is constructed
153
// manually and the FrameScope does not need to emit code.
158
// Opaque data type for identifying stack frames. Used extensively
160
// ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
161
// has correct value range (see Issue 830 for more details).
163
ID_MIN_VALUE = kMinInt,
164
ID_MAX_VALUE = kMaxInt,
168
// Used to mark the outermost JS entry frame.
170
INNER_JSENTRY_FRAME = 0,
171
OUTERMOST_JSENTRY_FRAME = 1
175
State() : sp(NULL), fp(NULL), pc_address(NULL) { }
181
// Copy constructor; it breaks the connection to host iterator
182
// (as an iterator usually lives on stack).
183
StackFrame(const StackFrame& original) {
184
this->state_ = original.state_;
185
this->iterator_ = NULL;
186
this->isolate_ = original.isolate_;
190
bool is_entry() const { return type() == ENTRY; }
191
bool is_entry_construct() const { return type() == ENTRY_CONSTRUCT; }
192
bool is_exit() const { return type() == EXIT; }
193
bool is_optimized() const { return type() == OPTIMIZED; }
194
bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
195
bool is_internal() const { return type() == INTERNAL; }
196
bool is_construct() const { return type() == CONSTRUCT; }
197
virtual bool is_standard() const { return false; }
199
bool is_java_script() const {
200
Type type = this->type();
201
return (type == JAVA_SCRIPT) || (type == OPTIMIZED);
205
Address sp() const { return state_.sp; }
206
Address fp() const { return state_.fp; }
207
Address caller_sp() const { return GetCallerStackPointer(); }
209
// If this frame is optimized and was dynamically aligned return its old
210
// unaligned frame pointer. When the frame is deoptimized its FP will shift
211
// up one word and become unaligned.
212
Address UnpaddedFP() const;
214
Address pc() const { return *pc_address(); }
215
void set_pc(Address pc) { *pc_address() = pc; }
217
virtual void SetCallerFp(Address caller_fp) = 0;
219
// Manually changes value of fp in this object.
220
void UpdateFp(Address fp) { state_.fp = fp; }
222
Address* pc_address() const { return state_.pc_address; }
224
// Get the id of this stack frame.
225
Id id() const { return static_cast<Id>(OffsetFrom(caller_sp())); }
227
// Checks if this frame includes any stack handlers.
228
bool HasHandler() const;
230
// Get the type of this frame.
231
virtual Type type() const = 0;
233
// Get the code associated with this frame.
234
// This method could be called during marking phase of GC.
235
virtual Code* unchecked_code() const = 0;
237
// Get the code associated with this frame.
238
inline Code* LookupCode() const;
240
// Get the code object that contains the given pc.
241
static inline Code* GetContainingCode(Isolate* isolate, Address pc);
243
// Get the code object containing the given pc and fill in the
244
// safepoint entry and the number of stack slots. The pc must be at
246
static Code* GetSafepointData(Isolate* isolate,
248
SafepointEntry* safepoint_entry,
249
unsigned* stack_slots);
251
virtual void Iterate(ObjectVisitor* v) const = 0;
252
static void IteratePc(ObjectVisitor* v, Address* pc_address, Code* holder);
254
// Sets a callback function for return-address rewriting profilers
255
// to resolve the location of a return address to the location of the
256
// profiler's stashed return address.
257
static void SetReturnAddressLocationResolver(
258
ReturnAddressLocationResolver resolver);
261
enum PrintMode { OVERVIEW, DETAILS };
262
virtual void Print(StringStream* accumulator,
267
inline explicit StackFrame(StackFrameIterator* iterator);
268
virtual ~StackFrame() { }
270
Isolate* isolate() const { return isolate_; }
272
// Compute the stack pointer for the calling frame.
273
virtual Address GetCallerStackPointer() const = 0;
276
static void PrintIndex(StringStream* accumulator,
280
// Get the top handler from the current stack iterator.
281
inline StackHandler* top_handler() const;
283
// Compute the stack frame type for the given state.
284
static Type ComputeType(Isolate* isolate, State* state);
287
const StackFrameIterator* iterator_;
291
// Fill in the state of the calling frame.
292
virtual void ComputeCallerState(State* state) const = 0;
294
// Get the type and the state of the calling frame.
295
virtual Type GetCallerState(State* state) const;
297
static const intptr_t kIsolateTag = 1;
299
friend class StackFrameIterator;
300
friend class StackHandlerIterator;
301
friend class SafeStackFrameIterator;
304
void operator=(const StackFrame& original);
308
// Entry frames are used to enter JavaScript execution from C.
309
class EntryFrame: public StackFrame {
311
virtual Type type() const { return ENTRY; }
313
virtual Code* unchecked_code() const;
315
// Garbage collection support.
316
virtual void Iterate(ObjectVisitor* v) const;
318
static EntryFrame* cast(StackFrame* frame) {
319
ASSERT(frame->is_entry());
320
return static_cast<EntryFrame*>(frame);
322
virtual void SetCallerFp(Address caller_fp);
325
inline explicit EntryFrame(StackFrameIterator* iterator);
327
// The caller stack pointer for entry frames is always zero. The
328
// real information about the caller frame is available through the
329
// link to the top exit frame.
330
virtual Address GetCallerStackPointer() const { return 0; }
333
virtual void ComputeCallerState(State* state) const;
334
virtual Type GetCallerState(State* state) const;
336
friend class StackFrameIterator;
340
class EntryConstructFrame: public EntryFrame {
342
virtual Type type() const { return ENTRY_CONSTRUCT; }
344
virtual Code* unchecked_code() const;
346
static EntryConstructFrame* cast(StackFrame* frame) {
347
ASSERT(frame->is_entry_construct());
348
return static_cast<EntryConstructFrame*>(frame);
352
inline explicit EntryConstructFrame(StackFrameIterator* iterator);
355
friend class StackFrameIterator;
359
// Exit frames are used to exit JavaScript execution and go to C.
360
class ExitFrame: public StackFrame {
362
virtual Type type() const { return EXIT; }
364
virtual Code* unchecked_code() const;
366
Object*& code_slot() const;
368
// Garbage collection support.
369
virtual void Iterate(ObjectVisitor* v) const;
371
virtual void SetCallerFp(Address caller_fp);
373
static ExitFrame* cast(StackFrame* frame) {
374
ASSERT(frame->is_exit());
375
return static_cast<ExitFrame*>(frame);
378
// Compute the state and type of an exit frame given a frame
379
// pointer. Used when constructing the first stack frame seen by an
380
// iterator and the frames following entry frames.
381
static Type GetStateForFramePointer(Address fp, State* state);
382
static Address ComputeStackPointer(Address fp);
383
static void FillState(Address fp, Address sp, State* state);
386
inline explicit ExitFrame(StackFrameIterator* iterator);
388
virtual Address GetCallerStackPointer() const;
391
virtual void ComputeCallerState(State* state) const;
393
friend class StackFrameIterator;
397
class StandardFrame: public StackFrame {
400
virtual bool is_standard() const { return true; }
403
inline Object* context() const;
405
// Access the expressions in the stack frame including locals.
406
inline Object* GetExpression(int index) const;
407
inline void SetExpression(int index, Object* value);
408
int ComputeExpressionsCount() const;
409
static Object* GetExpression(Address fp, int index);
411
virtual void SetCallerFp(Address caller_fp);
413
static StandardFrame* cast(StackFrame* frame) {
414
ASSERT(frame->is_standard());
415
return static_cast<StandardFrame*>(frame);
419
inline explicit StandardFrame(StackFrameIterator* iterator);
421
virtual void ComputeCallerState(State* state) const;
424
inline Address caller_fp() const;
425
inline Address caller_pc() const;
427
// Computes the address of the PC field in the standard frame given
428
// by the provided frame pointer.
429
static inline Address ComputePCAddress(Address fp);
431
// Iterate over expression stack including stack handlers, locals,
432
// and parts of the fixed part including context and code fields.
433
void IterateExpressions(ObjectVisitor* v) const;
435
// Returns the address of the n'th expression stack element.
436
Address GetExpressionAddress(int n) const;
437
static Address GetExpressionAddress(Address fp, int n);
439
// Determines if the n'th expression stack element is in a stack
440
// handler or not. Requires traversing all handlers in this frame.
441
bool IsExpressionInsideHandler(int n) const;
443
// Determines if the standard frame for the given frame pointer is
444
// an arguments adaptor frame.
445
static inline bool IsArgumentsAdaptorFrame(Address fp);
447
// Determines if the standard frame for the given frame pointer is a
449
static inline bool IsConstructFrame(Address fp);
452
friend class StackFrame;
453
friend class StackFrameIterator;
457
class FrameSummary BASE_EMBEDDED {
459
FrameSummary(Object* receiver,
460
JSFunction* function,
464
: receiver_(receiver),
468
is_constructor_(is_constructor) { }
469
Handle<Object> receiver() { return receiver_; }
470
Handle<JSFunction> function() { return function_; }
471
Handle<Code> code() { return code_; }
472
Address pc() { return code_->address() + offset_; }
473
int offset() { return offset_; }
474
bool is_constructor() { return is_constructor_; }
479
Handle<Object> receiver_;
480
Handle<JSFunction> function_;
483
bool is_constructor_;
487
class JavaScriptFrame: public StandardFrame {
489
virtual Type type() const { return JAVA_SCRIPT; }
492
inline Object* function() const;
493
inline Object* receiver() const;
494
inline void set_receiver(Object* value);
496
// Access the parameters.
497
inline Address GetParameterSlot(int index) const;
498
inline Object* GetParameter(int index) const;
499
inline int ComputeParametersCount() const {
500
return GetNumberOfIncomingArguments();
503
// Check if this frame is a constructor frame invoked through 'new'.
504
bool IsConstructor() const;
506
// Check if this frame has "adapted" arguments in the sense that the
507
// actual passed arguments are available in an arguments adaptor
508
// frame below it on the stack.
509
inline bool has_adapted_arguments() const;
510
int GetArgumentsLength() const;
512
// Garbage collection support.
513
virtual void Iterate(ObjectVisitor* v) const;
516
virtual void Print(StringStream* accumulator,
520
// Determine the code for the frame.
521
virtual Code* unchecked_code() const;
523
// Returns the levels of inlining for this frame.
524
virtual int GetInlineCount() { return 1; }
526
// Return a list with JSFunctions of this frame.
527
virtual void GetFunctions(List<JSFunction*>* functions);
529
// Build a list with summaries for this frame including all inlined frames.
530
virtual void Summarize(List<FrameSummary>* frames);
532
static JavaScriptFrame* cast(StackFrame* frame) {
533
ASSERT(frame->is_java_script());
534
return static_cast<JavaScriptFrame*>(frame);
537
static void PrintTop(FILE* file, bool print_args, bool print_line_number);
540
inline explicit JavaScriptFrame(StackFrameIterator* iterator);
542
virtual Address GetCallerStackPointer() const;
544
virtual int GetNumberOfIncomingArguments() const;
546
// Garbage collection support. Iterates over incoming arguments,
547
// receiver, and any callee-saved registers.
548
void IterateArguments(ObjectVisitor* v) const;
551
inline Object* function_slot_object() const;
553
friend class StackFrameIterator;
554
friend class StackTracer;
558
class OptimizedFrame : public JavaScriptFrame {
560
virtual Type type() const { return OPTIMIZED; }
563
virtual void Iterate(ObjectVisitor* v) const;
565
virtual int GetInlineCount();
567
// Return a list with JSFunctions of this frame.
568
// The functions are ordered bottom-to-top (i.e. functions.last()
569
// is the top-most activation)
570
virtual void GetFunctions(List<JSFunction*>* functions);
572
virtual void Summarize(List<FrameSummary>* frames);
574
DeoptimizationInputData* GetDeoptimizationData(int* deopt_index);
577
inline explicit OptimizedFrame(StackFrameIterator* iterator);
580
JSFunction* LiteralAt(FixedArray* literal_array, int literal_id);
582
friend class StackFrameIterator;
586
// Arguments adaptor frames are automatically inserted below
587
// JavaScript frames when the actual number of parameters does not
588
// match the formal number of parameters.
589
class ArgumentsAdaptorFrame: public JavaScriptFrame {
591
virtual Type type() const { return ARGUMENTS_ADAPTOR; }
593
// Determine the code for the frame.
594
virtual Code* unchecked_code() const;
596
static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
597
ASSERT(frame->is_arguments_adaptor());
598
return static_cast<ArgumentsAdaptorFrame*>(frame);
602
virtual void Print(StringStream* accumulator,
607
inline explicit ArgumentsAdaptorFrame(StackFrameIterator* iterator);
609
virtual int GetNumberOfIncomingArguments() const;
611
virtual Address GetCallerStackPointer() const;
614
friend class StackFrameIterator;
618
class InternalFrame: public StandardFrame {
620
virtual Type type() const { return INTERNAL; }
622
// Garbage collection support.
623
virtual void Iterate(ObjectVisitor* v) const;
625
// Determine the code for the frame.
626
virtual Code* unchecked_code() const;
628
static InternalFrame* cast(StackFrame* frame) {
629
ASSERT(frame->is_internal());
630
return static_cast<InternalFrame*>(frame);
634
inline explicit InternalFrame(StackFrameIterator* iterator);
636
virtual Address GetCallerStackPointer() const;
639
friend class StackFrameIterator;
643
// Construct frames are special trampoline frames introduced to handle
644
// function invocations through 'new'.
645
class ConstructFrame: public InternalFrame {
647
virtual Type type() const { return CONSTRUCT; }
649
static ConstructFrame* cast(StackFrame* frame) {
650
ASSERT(frame->is_construct());
651
return static_cast<ConstructFrame*>(frame);
655
inline explicit ConstructFrame(StackFrameIterator* iterator);
658
friend class StackFrameIterator;
662
class StackFrameIterator BASE_EMBEDDED {
664
// An iterator that iterates over the current thread's stack,
665
// and uses current isolate.
666
StackFrameIterator();
668
// An iterator that iterates over the isolate's current thread's stack,
669
explicit StackFrameIterator(Isolate* isolate);
671
// An iterator that iterates over a given thread's stack.
672
StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
674
// An iterator that can start from a given FP address.
675
// If use_top, then work as usual, if fp isn't NULL, use it,
676
// otherwise, do nothing.
677
StackFrameIterator(Isolate* isolate, bool use_top, Address fp, Address sp);
679
StackFrame* frame() const {
684
Isolate* isolate() const { return isolate_; }
686
bool done() const { return frame_ == NULL; }
687
void Advance() { (this->*advance_)(); }
689
// Go back to the first frame.
694
#define DECLARE_SINGLETON(ignore, type) type type##_;
695
STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
696
#undef DECLARE_SINGLETON
698
StackHandler* handler_;
699
ThreadLocalTop* thread_;
702
void (StackFrameIterator::*advance_)();
704
StackHandler* handler() const {
709
// Get the type-specific frame singleton in a given state.
710
StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
711
// A helper function, can return a NULL pointer.
712
StackFrame* SingletonFor(StackFrame::Type type);
714
void AdvanceWithHandler();
715
void AdvanceWithoutHandler();
717
friend class StackFrame;
718
friend class SafeStackFrameIterator;
719
DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
723
// Iterator that supports iterating through all JavaScript frames.
724
template<typename Iterator>
725
class JavaScriptFrameIteratorTemp BASE_EMBEDDED {
727
JavaScriptFrameIteratorTemp() { if (!done()) Advance(); }
729
inline explicit JavaScriptFrameIteratorTemp(Isolate* isolate);
731
inline JavaScriptFrameIteratorTemp(Isolate* isolate, ThreadLocalTop* top);
733
// Skip frames until the frame with the given id is reached.
734
explicit JavaScriptFrameIteratorTemp(StackFrame::Id id) { AdvanceToId(id); }
736
inline JavaScriptFrameIteratorTemp(Isolate* isolate, StackFrame::Id id);
738
JavaScriptFrameIteratorTemp(Address fp,
741
Address high_bound) :
742
iterator_(fp, sp, low_bound, high_bound) {
743
if (!done()) Advance();
746
JavaScriptFrameIteratorTemp(Isolate* isolate,
750
Address high_bound) :
751
iterator_(isolate, fp, sp, low_bound, high_bound) {
752
if (!done()) Advance();
755
inline JavaScriptFrame* frame() const;
757
bool done() const { return iterator_.done(); }
760
// Advance to the frame holding the arguments for the current
761
// frame. This only affects the current frame if it has adapted
763
void AdvanceToArgumentsFrame();
765
// Go back to the first frame.
769
inline void AdvanceToId(StackFrame::Id id);
775
typedef JavaScriptFrameIteratorTemp<StackFrameIterator> JavaScriptFrameIterator;
778
// NOTE: The stack trace frame iterator is an iterator that only
779
// traverse proper JavaScript frames; that is JavaScript frames that
780
// have proper JavaScript functions. This excludes the problematic
781
// functions in runtime.js.
782
class StackTraceFrameIterator: public JavaScriptFrameIterator {
784
StackTraceFrameIterator();
785
explicit StackTraceFrameIterator(Isolate* isolate);
793
class SafeStackFrameIterator BASE_EMBEDDED {
795
SafeStackFrameIterator(Isolate* isolate,
796
Address fp, Address sp,
797
Address low_bound, Address high_bound);
799
StackFrame* frame() const {
800
ASSERT(is_working_iterator_);
801
return iterator_.frame();
804
bool done() const { return iteration_done_ ? true : iterator_.done(); }
809
static bool is_active(Isolate* isolate);
811
static bool IsWithinBounds(
812
Address low_bound, Address high_bound, Address addr) {
813
return low_bound <= addr && addr <= high_bound;
817
class StackAddressValidator {
819
StackAddressValidator(Address low_bound, Address high_bound)
820
: low_bound_(low_bound), high_bound_(high_bound) { }
821
bool IsValid(Address addr) const {
822
return IsWithinBounds(low_bound_, high_bound_, addr);
829
class ExitFrameValidator {
831
explicit ExitFrameValidator(const StackAddressValidator& validator)
832
: validator_(validator) { }
833
ExitFrameValidator(Address low_bound, Address high_bound)
834
: validator_(low_bound, high_bound) { }
835
bool IsValidFP(Address fp);
837
StackAddressValidator validator_;
840
bool IsValidStackAddress(Address addr) const {
841
return stack_validator_.IsValid(addr);
843
bool CanIterateHandles(StackFrame* frame, StackHandler* handler);
844
bool IsValidFrame(StackFrame* frame) const;
845
bool IsValidCaller(StackFrame* frame);
846
static bool IsValidTop(Isolate* isolate,
847
Address low_bound, Address high_bound);
849
// This is a nasty hack to make sure the active count is incremented
850
// before the constructor for the embedded iterator is invoked. This
851
// is needed because the constructor will start looking at frames
852
// right away and we need to make sure it doesn't start inspecting
854
class ActiveCountMaintainer BASE_EMBEDDED {
856
explicit ActiveCountMaintainer(Isolate* isolate);
857
~ActiveCountMaintainer();
862
ActiveCountMaintainer maintainer_;
863
StackAddressValidator stack_validator_;
864
const bool is_valid_top_;
865
const bool is_valid_fp_;
866
const bool is_working_iterator_;
867
bool iteration_done_;
868
StackFrameIterator iterator_;
872
typedef JavaScriptFrameIteratorTemp<SafeStackFrameIterator>
873
SafeJavaScriptFrameIterator;
876
class SafeStackTraceFrameIterator: public SafeJavaScriptFrameIterator {
878
explicit SafeStackTraceFrameIterator(Isolate* isolate,
879
Address fp, Address sp,
880
Address low_bound, Address high_bound);
885
class StackFrameLocator BASE_EMBEDDED {
887
// Find the nth JavaScript frame on the stack. The caller must
888
// guarantee that such a frame exists.
889
JavaScriptFrame* FindJavaScriptFrame(int n);
892
StackFrameIterator iterator_;
896
// Reads all frames on the current stack and copies them into the current
898
Vector<StackFrame*> CreateStackMap(Zone* zone);
900
} } // namespace v8::internal
902
#endif // V8_FRAMES_H_