1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef V8_FRAMES_H_
6#define V8_FRAMES_H_
7
8#include "src/handles.h"
9#include "src/objects.h"
10#include "src/objects/code.h"
11#include "src/safepoint-table.h"
12
13namespace v8 {
14namespace internal {
15namespace wasm {
16class WasmCode;
17}
18
19// Forward declarations.
20class AbstractCode;
21class Debug;
22class ExternalCallbackScope;
23class InnerPointerToCodeCache;
24class Isolate;
25class ObjectVisitor;
26class RootVisitor;
27class StackFrameIteratorBase;
28class StringStream;
29class ThreadLocalTop;
30class WasmDebugInfo;
31class WasmInstanceObject;
32class WasmModuleObject;
33
34class StackHandlerConstants : public AllStatic {
35 public:
36 static const int kNextOffset = 0 * kSystemPointerSize;
37 static const int kPaddingOffset = 1 * kSystemPointerSize;
38
39 static const int kSize = kPaddingOffset + kSystemPointerSize;
40 static const int kSlotCount = kSize >> kSystemPointerSizeLog2;
41};
42
43class StackHandler {
44 public:
45 // Get the address of this stack handler.
46 inline Address address() const;
47
48 // Get the next stack handler in the chain.
49 inline StackHandler* next() const;
50
51 // Get the next stack handler, as an Address. This is safe to use even
52 // when the next handler is null.
53 inline Address next_address() const;
54
55 // Conversion support.
56 static inline StackHandler* FromAddress(Address address);
57
58 private:
59 DISALLOW_IMPLICIT_CONSTRUCTORS(StackHandler);
60};
61
62#define STACK_FRAME_TYPE_LIST(V) \
63 V(ENTRY, EntryFrame) \
64 V(CONSTRUCT_ENTRY, ConstructEntryFrame) \
65 V(EXIT, ExitFrame) \
66 V(OPTIMIZED, OptimizedFrame) \
67 V(WASM_COMPILED, WasmCompiledFrame) \
68 V(WASM_TO_JS, WasmToJsFrame) \
69 V(JS_TO_WASM, JsToWasmFrame) \
70 V(WASM_INTERPRETER_ENTRY, WasmInterpreterEntryFrame) \
71 V(C_WASM_ENTRY, CWasmEntryFrame) \
72 V(WASM_COMPILE_LAZY, WasmCompileLazyFrame) \
73 V(INTERPRETED, InterpretedFrame) \
74 V(STUB, StubFrame) \
75 V(BUILTIN_CONTINUATION, BuiltinContinuationFrame) \
76 V(JAVA_SCRIPT_BUILTIN_CONTINUATION, JavaScriptBuiltinContinuationFrame) \
77 V(JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH, \
78 JavaScriptBuiltinContinuationWithCatchFrame) \
79 V(INTERNAL, InternalFrame) \
80 V(CONSTRUCT, ConstructFrame) \
81 V(ARGUMENTS_ADAPTOR, ArgumentsAdaptorFrame) \
82 V(BUILTIN, BuiltinFrame) \
83 V(BUILTIN_EXIT, BuiltinExitFrame) \
84 V(NATIVE, NativeFrame)
85
86// Abstract base class for all stack frames.
87class StackFrame {
88 public:
89#define DECLARE_TYPE(type, ignore) type,
90 enum Type {
91 NONE = 0,
92 STACK_FRAME_TYPE_LIST(DECLARE_TYPE)
93 NUMBER_OF_TYPES,
94 // Used by FrameScope to indicate that the stack frame is constructed
95 // manually and the FrameScope does not need to emit code.
96 MANUAL
97 };
98#undef DECLARE_TYPE
99
100 // Opaque data type for identifying stack frames. Used extensively
101 // by the debugger.
102 // ID_MIN_VALUE and ID_MAX_VALUE are specified to ensure that enumeration type
103 // has correct value range (see Issue 830 for more details).
104 enum Id {
105 ID_MIN_VALUE = kMinInt,
106 ID_MAX_VALUE = kMaxInt,
107 NO_ID = 0
108 };
109
110 // Used to mark the outermost JS entry frame.
111 //
112 // The mark is an opaque value that should be pushed onto the stack directly,
113 // carefully crafted to not be interpreted as a tagged pointer.
114 enum JsFrameMarker {
115 INNER_JSENTRY_FRAME = (0 << kSmiTagSize) | kSmiTag,
116 OUTERMOST_JSENTRY_FRAME = (1 << kSmiTagSize) | kSmiTag
117 };
118 STATIC_ASSERT((INNER_JSENTRY_FRAME & kHeapObjectTagMask) != kHeapObjectTag);
119 STATIC_ASSERT((OUTERMOST_JSENTRY_FRAME & kHeapObjectTagMask) !=
120 kHeapObjectTag);
121
122 struct State {
123 Address sp = kNullAddress;
124 Address fp = kNullAddress;
125 Address* pc_address = nullptr;
126 Address* callee_pc_address = nullptr;
127 Address* constant_pool_address = nullptr;
128 };
129
130 // Convert a stack frame type to a marker that can be stored on the stack.
131 //
132 // The marker is an opaque value, not intended to be interpreted in any way
133 // except being checked by IsTypeMarker or converted by MarkerToType.
134 // It has the same tagging as Smis, so any marker value that does not pass
135 // IsTypeMarker can instead be interpreted as a tagged pointer.
136 //
137 // Note that the marker is not a Smi: Smis on 64-bit architectures are stored
138 // in the top 32 bits of a 64-bit value, which in turn makes them expensive
139 // (in terms of code/instruction size) to push as immediates onto the stack.
140 static int32_t TypeToMarker(Type type) {
141 DCHECK_GE(type, 0);
142 return (type << kSmiTagSize) | kSmiTag;
143 }
144
145 // Convert a marker back to a stack frame type.
146 //
147 // Unlike the return value of TypeToMarker, this takes an intptr_t, as that is
148 // the type of the value on the stack.
149 static Type MarkerToType(intptr_t marker) {
150 DCHECK(IsTypeMarker(marker));
151 return static_cast<Type>(marker >> kSmiTagSize);
152 }
153
154 // Check if a marker is a stack frame type marker or a tagged pointer.
155 //
156 // Returns true if the given marker is tagged as a stack frame type marker,
157 // and should be converted back to a stack frame type using MarkerToType.
158 // Otherwise, the value is a tagged function pointer.
159 static bool IsTypeMarker(intptr_t function_or_marker) {
160 return (function_or_marker & kSmiTagMask) == kSmiTag;
161 }
162
163 // Copy constructor; it breaks the connection to host iterator
164 // (as an iterator usually lives on stack).
165 StackFrame(const StackFrame& original) V8_NOEXCEPT {
166 this->state_ = original.state_;
167 this->iterator_ = nullptr;
168 this->isolate_ = original.isolate_;
169 }
170
171 // Type testers.
172 bool is_entry() const { return type() == ENTRY; }
173 bool is_construct_entry() const { return type() == CONSTRUCT_ENTRY; }
174 bool is_exit() const { return type() == EXIT; }
175 bool is_optimized() const { return type() == OPTIMIZED; }
176 bool is_interpreted() const { return type() == INTERPRETED; }
177 bool is_wasm_compiled() const { return type() == WASM_COMPILED; }
178 bool is_wasm_compile_lazy() const { return type() == WASM_COMPILE_LAZY; }
179 bool is_wasm_to_js() const { return type() == WASM_TO_JS; }
180 bool is_js_to_wasm() const { return type() == JS_TO_WASM; }
181 bool is_wasm_interpreter_entry() const {
182 return type() == WASM_INTERPRETER_ENTRY;
183 }
184 bool is_arguments_adaptor() const { return type() == ARGUMENTS_ADAPTOR; }
185 bool is_builtin() const { return type() == BUILTIN; }
186 bool is_internal() const { return type() == INTERNAL; }
187 bool is_builtin_continuation() const {
188 return type() == BUILTIN_CONTINUATION;
189 }
190 bool is_java_script_builtin_continuation() const {
191 return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION;
192 }
193 bool is_java_script_builtin_with_catch_continuation() const {
194 return type() == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
195 }
196 bool is_construct() const { return type() == CONSTRUCT; }
197 bool is_builtin_exit() const { return type() == BUILTIN_EXIT; }
198 virtual bool is_standard() const { return false; }
199
200 bool is_java_script() const {
201 Type type = this->type();
202 return (type == OPTIMIZED) || (type == INTERPRETED) || (type == BUILTIN) ||
203 (type == JAVA_SCRIPT_BUILTIN_CONTINUATION) ||
204 (type == JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH);
205 }
206 bool is_wasm() const {
207 Type type = this->type();
208 return type == WASM_COMPILED || type == WASM_INTERPRETER_ENTRY;
209 }
210
211 // Accessors.
212 Address sp() const { return state_.sp; }
213 Address fp() const { return state_.fp; }
214 Address callee_pc() const {
215 return state_.callee_pc_address ? *state_.callee_pc_address : kNullAddress;
216 }
217 Address caller_sp() const { return GetCallerStackPointer(); }
218
219 // If this frame is optimized and was dynamically aligned return its old
220 // unaligned frame pointer. When the frame is deoptimized its FP will shift
221 // up one word and become unaligned.
222 Address UnpaddedFP() const;
223
224 Address pc() const { return *pc_address(); }
225 void set_pc(Address pc) { *pc_address() = pc; }
226
227 Address constant_pool() const { return *constant_pool_address(); }
228 void set_constant_pool(Address constant_pool) {
229 *constant_pool_address() = constant_pool;
230 }
231
232 Address* pc_address() const { return state_.pc_address; }
233
234 Address* constant_pool_address() const {
235 return state_.constant_pool_address;
236 }
237
238 // Get the id of this stack frame.
239 Id id() const { return static_cast<Id>(caller_sp()); }
240
241 // Get the top handler from the current stack iterator.
242 inline StackHandler* top_handler() const;
243
244 // Get the type of this frame.
245 virtual Type type() const = 0;
246
247 // Get the code associated with this frame.
248 // This method could be called during marking phase of GC.
249 virtual Code unchecked_code() const = 0;
250
251 // Search for the code associated with this frame.
252 V8_EXPORT_PRIVATE Code LookupCode() const;
253
254 virtual void Iterate(RootVisitor* v) const = 0;
255 static void IteratePc(RootVisitor* v, Address* pc_address,
256 Address* constant_pool_address, Code holder);
257
258 // Sets a callback function for return-address rewriting profilers
259 // to resolve the location of a return address to the location of the
260 // profiler's stashed return address.
261 static void SetReturnAddressLocationResolver(
262 ReturnAddressLocationResolver resolver);
263
264 // Resolves pc_address through the resolution address function if one is set.
265 static inline Address* ResolveReturnAddressLocation(Address* pc_address);
266
267 // Printing support.
268 enum PrintMode { OVERVIEW, DETAILS };
269 virtual void Print(StringStream* accumulator, PrintMode mode,
270 int index) const;
271
272 Isolate* isolate() const { return isolate_; }
273
274 void operator=(const StackFrame& original) = delete;
275
276 protected:
277 inline explicit StackFrame(StackFrameIteratorBase* iterator);
278 virtual ~StackFrame() = default;
279
280 // Compute the stack pointer for the calling frame.
281 virtual Address GetCallerStackPointer() const = 0;
282
283 // Compute the stack frame type for the given state.
284 static Type ComputeType(const StackFrameIteratorBase* iterator, State* state);
285
286#ifdef DEBUG
287 bool can_access_heap_objects() const;
288#endif
289
290 private:
291 const StackFrameIteratorBase* iterator_;
292 Isolate* isolate_;
293 State state_;
294
295 static ReturnAddressLocationResolver return_address_location_resolver_;
296
297 // Fill in the state of the calling frame.
298 virtual void ComputeCallerState(State* state) const = 0;
299
300 // Get the type and the state of the calling frame.
301 virtual Type GetCallerState(State* state) const;
302
303 static const intptr_t kIsolateTag = 1;
304
305 friend class StackFrameIterator;
306 friend class StackFrameIteratorBase;
307 friend class StackHandlerIterator;
308 friend class SafeStackFrameIterator;
309};
310
311class NativeFrame : public StackFrame {
312 public:
313 Type type() const override { return NATIVE; }
314
315 Code unchecked_code() const override;
316
317 // Garbage collection support.
318 void Iterate(RootVisitor* v) const override {}
319
320 protected:
321 inline explicit NativeFrame(StackFrameIteratorBase* iterator);
322
323 Address GetCallerStackPointer() const override;
324
325 private:
326 void ComputeCallerState(State* state) const override;
327
328 friend class StackFrameIteratorBase;
329};
330
331// Entry frames are used to enter JavaScript execution from C.
332class EntryFrame: public StackFrame {
333 public:
334 Type type() const override { return ENTRY; }
335
336 Code unchecked_code() const override;
337
338 // Garbage collection support.
339 void Iterate(RootVisitor* v) const override;
340
341 static EntryFrame* cast(StackFrame* frame) {
342 DCHECK(frame->is_entry());
343 return static_cast<EntryFrame*>(frame);
344 }
345
346 protected:
347 inline explicit EntryFrame(StackFrameIteratorBase* iterator);
348
349 // The caller stack pointer for entry frames is always zero. The
350 // real information about the caller frame is available through the
351 // link to the top exit frame.
352 Address GetCallerStackPointer() const override { return 0; }
353
354 private:
355 void ComputeCallerState(State* state) const override;
356 Type GetCallerState(State* state) const override;
357
358 friend class StackFrameIteratorBase;
359};
360
361class ConstructEntryFrame : public EntryFrame {
362 public:
363 Type type() const override { return CONSTRUCT_ENTRY; }
364
365 Code unchecked_code() const override;
366
367 static ConstructEntryFrame* cast(StackFrame* frame) {
368 DCHECK(frame->is_construct_entry());
369 return static_cast<ConstructEntryFrame*>(frame);
370 }
371
372 protected:
373 inline explicit ConstructEntryFrame(StackFrameIteratorBase* iterator);
374
375 private:
376 friend class StackFrameIteratorBase;
377};
378
379
380// Exit frames are used to exit JavaScript execution and go to C.
381class ExitFrame: public StackFrame {
382 public:
383 Type type() const override { return EXIT; }
384
385 Code unchecked_code() const override;
386
387 // Garbage collection support.
388 void Iterate(RootVisitor* v) const override;
389
390 static ExitFrame* cast(StackFrame* frame) {
391 DCHECK(frame->is_exit());
392 return static_cast<ExitFrame*>(frame);
393 }
394
395 // Compute the state and type of an exit frame given a frame
396 // pointer. Used when constructing the first stack frame seen by an
397 // iterator and the frames following entry frames.
398 static Type GetStateForFramePointer(Address fp, State* state);
399 static Address ComputeStackPointer(Address fp);
400 static StackFrame::Type ComputeFrameType(Address fp);
401 static void FillState(Address fp, Address sp, State* state);
402
403 protected:
404 inline explicit ExitFrame(StackFrameIteratorBase* iterator);
405
406 Address GetCallerStackPointer() const override;
407
408 private:
409 void ComputeCallerState(State* state) const override;
410
411 friend class StackFrameIteratorBase;
412};
413
414// Builtin exit frames are a special case of exit frames, which are used
415// whenever C++ builtins (e.g., Math.acos) are called. Their main purpose is
416// to allow such builtins to appear in stack traces.
417class BuiltinExitFrame : public ExitFrame {
418 public:
419 Type type() const override { return BUILTIN_EXIT; }
420
421 static BuiltinExitFrame* cast(StackFrame* frame) {
422 DCHECK(frame->is_builtin_exit());
423 return static_cast<BuiltinExitFrame*>(frame);
424 }
425
426 JSFunction function() const;
427 Object receiver() const;
428
429 bool IsConstructor() const;
430
431 void Print(StringStream* accumulator, PrintMode mode,
432 int index) const override;
433
434 protected:
435 inline explicit BuiltinExitFrame(StackFrameIteratorBase* iterator);
436
437 private:
438 Object GetParameter(int i) const;
439 int ComputeParametersCount() const;
440
441 inline Object receiver_slot_object() const;
442 inline Object argc_slot_object() const;
443 inline Object target_slot_object() const;
444 inline Object new_target_slot_object() const;
445
446 friend class StackFrameIteratorBase;
447 friend class FrameArrayBuilder;
448};
449
450class StandardFrame;
451
452class V8_EXPORT_PRIVATE FrameSummary {
453 public:
454// Subclasses for the different summary kinds:
455#define FRAME_SUMMARY_VARIANTS(F) \
456 F(JAVA_SCRIPT, JavaScriptFrameSummary, java_script_summary_, JavaScript) \
457 F(WASM_COMPILED, WasmCompiledFrameSummary, wasm_compiled_summary_, \
458 WasmCompiled) \
459 F(WASM_INTERPRETED, WasmInterpretedFrameSummary, wasm_interpreted_summary_, \
460 WasmInterpreted)
461
462#define FRAME_SUMMARY_KIND(kind, type, field, desc) kind,
463 enum Kind { FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_KIND) };
464#undef FRAME_SUMMARY_KIND
465
466 class FrameSummaryBase {
467 public:
468 FrameSummaryBase(Isolate* isolate, Kind kind)
469 : isolate_(isolate), kind_(kind) {}
470 Isolate* isolate() const { return isolate_; }
471 Kind kind() const { return kind_; }
472
473 private:
474 Isolate* isolate_;
475 Kind kind_;
476 };
477
478 class JavaScriptFrameSummary : public FrameSummaryBase {
479 public:
480 JavaScriptFrameSummary(Isolate* isolate, Object receiver,
481 JSFunction function, AbstractCode abstract_code,
482 int code_offset, bool is_constructor,
483 FixedArray parameters);
484
485 void EnsureSourcePositionsAvailable();
486
487 Handle<Object> receiver() const { return receiver_; }
488 Handle<JSFunction> function() const { return function_; }
489 Handle<AbstractCode> abstract_code() const { return abstract_code_; }
490 int code_offset() const { return code_offset_; }
491 bool is_constructor() const { return is_constructor_; }
492 Handle<FixedArray> parameters() const { return parameters_; }
493 bool is_subject_to_debugging() const;
494 int SourcePosition() const;
495 int SourceStatementPosition() const;
496 Handle<Object> script() const;
497 Handle<String> FunctionName() const;
498 Handle<Context> native_context() const;
499
500 private:
501 Handle<Object> receiver_;
502 Handle<JSFunction> function_;
503 Handle<AbstractCode> abstract_code_;
504 int code_offset_;
505 bool is_constructor_;
506 Handle<FixedArray> parameters_;
507 };
508
509 class WasmFrameSummary : public FrameSummaryBase {
510 protected:
511 WasmFrameSummary(Isolate*, Kind, Handle<WasmInstanceObject>,
512 bool at_to_number_conversion);
513
514 public:
515 Handle<Object> receiver() const;
516 uint32_t function_index() const;
517 int byte_offset() const;
518 bool is_constructor() const { return false; }
519 bool is_subject_to_debugging() const { return true; }
520 int SourcePosition() const;
521 int SourceStatementPosition() const { return SourcePosition(); }
522 Handle<Script> script() const;
523 Handle<WasmInstanceObject> wasm_instance() const { return wasm_instance_; }
524 Handle<String> FunctionName() const;
525 Handle<Context> native_context() const;
526 bool at_to_number_conversion() const { return at_to_number_conversion_; }
527
528 private:
529 Handle<WasmInstanceObject> wasm_instance_;
530 bool at_to_number_conversion_;
531 };
532
533 class WasmCompiledFrameSummary : public WasmFrameSummary {
534 public:
535 WasmCompiledFrameSummary(Isolate*, Handle<WasmInstanceObject>,
536 wasm::WasmCode*, int code_offset,
537 bool at_to_number_conversion);
538 uint32_t function_index() const;
539 wasm::WasmCode* code() const { return code_; }
540 int code_offset() const { return code_offset_; }
541 int byte_offset() const;
542 static int GetWasmSourcePosition(const wasm::WasmCode* code, int offset);
543
544 private:
545 wasm::WasmCode* const code_;
546 int code_offset_;
547 };
548
549 class WasmInterpretedFrameSummary : public WasmFrameSummary {
550 public:
551 WasmInterpretedFrameSummary(Isolate*, Handle<WasmInstanceObject>,
552 uint32_t function_index, int byte_offset);
553 uint32_t function_index() const { return function_index_; }
554 int code_offset() const { return byte_offset_; }
555 int byte_offset() const { return byte_offset_; }
556
557 private:
558 uint32_t function_index_;
559 int byte_offset_;
560 };
561
562#define FRAME_SUMMARY_CONS(kind, type, field, desc) \
563 FrameSummary(type summ) : field(summ) {} // NOLINT
564 FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CONS)
565#undef FRAME_SUMMARY_CONS
566
567 ~FrameSummary();
568
569 static FrameSummary GetTop(const StandardFrame* frame);
570 static FrameSummary GetBottom(const StandardFrame* frame);
571 static FrameSummary GetSingle(const StandardFrame* frame);
572 static FrameSummary Get(const StandardFrame* frame, int index);
573
574 void EnsureSourcePositionsAvailable();
575
576 // Dispatched accessors.
577 Handle<Object> receiver() const;
578 int code_offset() const;
579 bool is_constructor() const;
580 bool is_subject_to_debugging() const;
581 Handle<Object> script() const;
582 int SourcePosition() const;
583 int SourceStatementPosition() const;
584 Handle<String> FunctionName() const;
585 Handle<Context> native_context() const;
586
587#define FRAME_SUMMARY_CAST(kind_, type, field, desc) \
588 bool Is##desc() const { return base_.kind() == kind_; } \
589 const type& As##desc() const { \
590 DCHECK_EQ(base_.kind(), kind_); \
591 return field; \
592 }
593 FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_CAST)
594#undef FRAME_SUMMARY_CAST
595
596 bool IsWasm() const { return IsWasmCompiled() || IsWasmInterpreted(); }
597 const WasmFrameSummary& AsWasm() const {
598 if (IsWasmCompiled()) return AsWasmCompiled();
599 return AsWasmInterpreted();
600 }
601
602 private:
603#define FRAME_SUMMARY_FIELD(kind, type, field, desc) type field;
604 union {
605 FrameSummaryBase base_;
606 FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_FIELD)
607 };
608#undef FRAME_SUMMARY_FIELD
609};
610
611class StandardFrame : public StackFrame {
612 public:
613 // Testers.
614 bool is_standard() const override { return true; }
615
616 // Accessors.
617 virtual Object receiver() const;
618 virtual Script script() const;
619 virtual Object context() const;
620 virtual int position() const;
621
622 // Access the expressions in the stack frame including locals.
623 inline Object GetExpression(int index) const;
624 inline void SetExpression(int index, Object value);
625 int ComputeExpressionsCount() const;
626
627 // Access the parameters.
628 virtual Object GetParameter(int index) const;
629 virtual int ComputeParametersCount() const;
630
631 // Check if this frame is a constructor frame invoked through 'new'.
632 virtual bool IsConstructor() const;
633
634 // Build a list with summaries for this frame including all inlined frames.
635 // The functions are ordered bottom-to-top (i.e. summaries.last() is the
636 // top-most activation; caller comes before callee).
637 virtual void Summarize(std::vector<FrameSummary>* frames) const;
638
639 static StandardFrame* cast(StackFrame* frame) {
640 DCHECK(frame->is_standard());
641 return static_cast<StandardFrame*>(frame);
642 }
643
644 protected:
645 inline explicit StandardFrame(StackFrameIteratorBase* iterator);
646
647 void ComputeCallerState(State* state) const override;
648
649 // Accessors.
650 inline Address caller_fp() const;
651 inline Address caller_pc() const;
652
653 // Computes the address of the PC field in the standard frame given
654 // by the provided frame pointer.
655 static inline Address ComputePCAddress(Address fp);
656
657 // Computes the address of the constant pool field in the standard
658 // frame given by the provided frame pointer.
659 static inline Address ComputeConstantPoolAddress(Address fp);
660
661 // Iterate over expression stack including stack handlers, locals,
662 // and parts of the fixed part including context and code fields.
663 void IterateExpressions(RootVisitor* v) const;
664
665 // Returns the address of the n'th expression stack element.
666 virtual Address GetExpressionAddress(int n) const;
667
668 // Determines if the standard frame for the given frame pointer is
669 // an arguments adaptor frame.
670 static inline bool IsArgumentsAdaptorFrame(Address fp);
671
672 // Determines if the standard frame for the given frame pointer is a
673 // construct frame.
674 static inline bool IsConstructFrame(Address fp);
675
676 // Used by OptimizedFrames and StubFrames.
677 void IterateCompiledFrame(RootVisitor* v) const;
678
679 private:
680 friend class StackFrame;
681 friend class SafeStackFrameIterator;
682};
683
684class JavaScriptFrame : public StandardFrame {
685 public:
686 Type type() const override = 0;
687
688 void Summarize(std::vector<FrameSummary>* frames) const override;
689
690 // Accessors.
691 virtual JSFunction function() const;
692 Object unchecked_function() const;
693 Object receiver() const override;
694 Object context() const override;
695 Script script() const override;
696
697 inline void set_receiver(Object value);
698
699 // Access the parameters.
700 inline Address GetParameterSlot(int index) const;
701 Object GetParameter(int index) const override;
702 int ComputeParametersCount() const override;
703 Handle<FixedArray> GetParameters() const;
704
705 // Debugger access.
706 void SetParameterValue(int index, Object value) const;
707
708 // Check if this frame is a constructor frame invoked through 'new'.
709 bool IsConstructor() const override;
710
711 // Determines whether this frame includes inlined activations. To get details
712 // about the inlined frames use {GetFunctions} and {Summarize}.
713 bool HasInlinedFrames() const;
714
715 // Check if this frame has "adapted" arguments in the sense that the
716 // actual passed arguments are available in an arguments adaptor
717 // frame below it on the stack.
718 inline bool has_adapted_arguments() const;
719
720 // Garbage collection support.
721 void Iterate(RootVisitor* v) const override;
722
723 // Printing support.
724 void Print(StringStream* accumulator, PrintMode mode,
725 int index) const override;
726
727 // Determine the code for the frame.
728 Code unchecked_code() const override;
729
730 // Return a list with {SharedFunctionInfo} objects of this frame.
731 virtual void GetFunctions(std::vector<SharedFunctionInfo>* functions) const;
732
733 void GetFunctions(std::vector<Handle<SharedFunctionInfo>>* functions) const;
734
735 // Lookup exception handler for current {pc}, returns -1 if none found. Also
736 // returns data associated with the handler site specific to the frame type:
737 // - OptimizedFrame : Data is the stack slot count of the entire frame.
738 // - InterpretedFrame: Data is the register index holding the context.
739 virtual int LookupExceptionHandlerInTable(
740 int* data, HandlerTable::CatchPrediction* prediction);
741
742 // Architecture-specific register description.
743 static Register fp_register();
744 static Register context_register();
745 static Register constant_pool_pointer_register();
746
747 static JavaScriptFrame* cast(StackFrame* frame) {
748 DCHECK(frame->is_java_script());
749 return static_cast<JavaScriptFrame*>(frame);
750 }
751
752 static void PrintFunctionAndOffset(JSFunction function, AbstractCode code,
753 int code_offset, FILE* file,
754 bool print_line_number);
755
756 static void PrintTop(Isolate* isolate, FILE* file, bool print_args,
757 bool print_line_number);
758
759 static void CollectFunctionAndOffsetForICStats(JSFunction function,
760 AbstractCode code,
761 int code_offset);
762
763 protected:
764 inline explicit JavaScriptFrame(StackFrameIteratorBase* iterator);
765
766 Address GetCallerStackPointer() const override;
767
768 virtual void PrintFrameKind(StringStream* accumulator) const {}
769
770 private:
771 inline Object function_slot_object() const;
772
773 friend class StackFrameIteratorBase;
774};
775
776
777class StubFrame : public StandardFrame {
778 public:
779 Type type() const override { return STUB; }
780
781 // GC support.
782 void Iterate(RootVisitor* v) const override;
783
784 // Determine the code for the frame.
785 Code unchecked_code() const override;
786
787 // Lookup exception handler for current {pc}, returns -1 if none found. Only
788 // TurboFan stub frames are supported. Also returns data associated with the
789 // handler site:
790 // - TurboFan stub: Data is the stack slot count of the entire frame.
791 int LookupExceptionHandlerInTable(int* data);
792
793 protected:
794 inline explicit StubFrame(StackFrameIteratorBase* iterator);
795
796 Address GetCallerStackPointer() const override;
797
798 friend class StackFrameIteratorBase;
799};
800
801
802class OptimizedFrame : public JavaScriptFrame {
803 public:
804 Type type() const override { return OPTIMIZED; }
805
806 // GC support.
807 void Iterate(RootVisitor* v) const override;
808
809 // Return a list with {SharedFunctionInfo} objects of this frame.
810 // The functions are ordered bottom-to-top (i.e. functions.last()
811 // is the top-most activation)
812 void GetFunctions(std::vector<SharedFunctionInfo>* functions) const override;
813
814 void Summarize(std::vector<FrameSummary>* frames) const override;
815
816 // Lookup exception handler for current {pc}, returns -1 if none found.
817 int LookupExceptionHandlerInTable(
818 int* data, HandlerTable::CatchPrediction* prediction) override;
819
820 DeoptimizationData GetDeoptimizationData(int* deopt_index) const;
821
822 Object receiver() const override;
823 int ComputeParametersCount() const override;
824
825 static int StackSlotOffsetRelativeToFp(int slot_index);
826
827 protected:
828 inline explicit OptimizedFrame(StackFrameIteratorBase* iterator);
829
830
831 private:
832 friend class StackFrameIteratorBase;
833
834 Object StackSlotAt(int index) const;
835};
836
837
838class InterpretedFrame : public JavaScriptFrame {
839 public:
840 Type type() const override { return INTERPRETED; }
841
842 // Accessors.
843 int position() const override;
844
845 // Lookup exception handler for current {pc}, returns -1 if none found.
846 int LookupExceptionHandlerInTable(
847 int* data, HandlerTable::CatchPrediction* prediction) override;
848
849 // Returns the current offset into the bytecode stream.
850 int GetBytecodeOffset() const;
851
852 // Updates the current offset into the bytecode stream, mainly used for stack
853 // unwinding to continue execution at a different bytecode offset.
854 void PatchBytecodeOffset(int new_offset);
855
856 // Returns the frame's current bytecode array.
857 BytecodeArray GetBytecodeArray() const;
858
859 // Updates the frame's BytecodeArray with |bytecode_array|. Used by the
860 // debugger to swap execution onto a BytecodeArray patched with breakpoints.
861 void PatchBytecodeArray(BytecodeArray bytecode_array);
862
863 // Access to the interpreter register file for this frame.
864 Object ReadInterpreterRegister(int register_index) const;
865 void WriteInterpreterRegister(int register_index, Object value);
866
867 // Build a list with summaries for this frame including all inlined frames.
868 void Summarize(std::vector<FrameSummary>* frames) const override;
869
870 static int GetBytecodeOffset(Address fp);
871
872 static InterpretedFrame* cast(StackFrame* frame) {
873 DCHECK(frame->is_interpreted());
874 return static_cast<InterpretedFrame*>(frame);
875 }
876
877 protected:
878 inline explicit InterpretedFrame(StackFrameIteratorBase* iterator);
879
880 Address GetExpressionAddress(int n) const override;
881
882 private:
883 friend class StackFrameIteratorBase;
884};
885
886
887// Arguments adaptor frames are automatically inserted below
888// JavaScript frames when the actual number of parameters does not
889// match the formal number of parameters.
890class ArgumentsAdaptorFrame: public JavaScriptFrame {
891 public:
892 Type type() const override { return ARGUMENTS_ADAPTOR; }
893
894 // Determine the code for the frame.
895 Code unchecked_code() const override;
896
897 static ArgumentsAdaptorFrame* cast(StackFrame* frame) {
898 DCHECK(frame->is_arguments_adaptor());
899 return static_cast<ArgumentsAdaptorFrame*>(frame);
900 }
901
902 int ComputeParametersCount() const override;
903
904 // Printing support.
905 void Print(StringStream* accumulator, PrintMode mode,
906 int index) const override;
907
908 protected:
909 inline explicit ArgumentsAdaptorFrame(StackFrameIteratorBase* iterator);
910
911
912 private:
913 friend class StackFrameIteratorBase;
914};
915
916// Builtin frames are built for builtins with JavaScript linkage, such as
917// various standard library functions (i.e. Math.asin, Math.floor, etc.).
918class BuiltinFrame final : public JavaScriptFrame {
919 public:
920 Type type() const final { return BUILTIN; }
921
922 static BuiltinFrame* cast(StackFrame* frame) {
923 DCHECK(frame->is_builtin());
924 return static_cast<BuiltinFrame*>(frame);
925 }
926 int ComputeParametersCount() const final;
927
928 protected:
929 inline explicit BuiltinFrame(StackFrameIteratorBase* iterator);
930
931 void PrintFrameKind(StringStream* accumulator) const override;
932
933 private:
934 friend class StackFrameIteratorBase;
935};
936
937class WasmCompiledFrame final : public StandardFrame {
938 public:
939 Type type() const override { return WASM_COMPILED; }
940
941 // GC support.
942 void Iterate(RootVisitor* v) const override;
943
944 // Printing support.
945 void Print(StringStream* accumulator, PrintMode mode,
946 int index) const override;
947
948 // Lookup exception handler for current {pc}, returns -1 if none found. Also
949 // returns the stack slot count of the entire frame.
950 int LookupExceptionHandlerInTable(int* data);
951
952 // Determine the code for the frame.
953 Code unchecked_code() const override;
954
955 // Accessors.
956 WasmInstanceObject wasm_instance() const;
957 wasm::WasmCode* wasm_code() const;
958 uint32_t function_index() const;
959 Script script() const override;
960 int position() const override;
961 bool at_to_number_conversion() const;
962
963 void Summarize(std::vector<FrameSummary>* frames) const override;
964
965 static WasmCompiledFrame* cast(StackFrame* frame) {
966 DCHECK(frame->is_wasm_compiled());
967 return static_cast<WasmCompiledFrame*>(frame);
968 }
969
970 protected:
971 inline explicit WasmCompiledFrame(StackFrameIteratorBase* iterator);
972
973 Address GetCallerStackPointer() const override;
974
975 private:
976 friend class StackFrameIteratorBase;
977 WasmModuleObject module_object() const;
978};
979
980class WasmInterpreterEntryFrame final : public StandardFrame {
981 public:
982 Type type() const override { return WASM_INTERPRETER_ENTRY; }
983
984 // GC support.
985 void Iterate(RootVisitor* v) const override;
986
987 // Printing support.
988 void Print(StringStream* accumulator, PrintMode mode,
989 int index) const override;
990
991 void Summarize(std::vector<FrameSummary>* frames) const override;
992
993 // Determine the code for the frame.
994 Code unchecked_code() const override;
995
996 // Accessors.
997 WasmDebugInfo debug_info() const;
998 WasmInstanceObject wasm_instance() const;
999
1000 Script script() const override;
1001 int position() const override;
1002 Object context() const override;
1003
1004 static WasmInterpreterEntryFrame* cast(StackFrame* frame) {
1005 DCHECK(frame->is_wasm_interpreter_entry());
1006 return static_cast<WasmInterpreterEntryFrame*>(frame);
1007 }
1008
1009 protected:
1010 inline explicit WasmInterpreterEntryFrame(StackFrameIteratorBase* iterator);
1011
1012 Address GetCallerStackPointer() const override;
1013
1014 private:
1015 friend class StackFrameIteratorBase;
1016 WasmModuleObject module_object() const;
1017};
1018
1019class WasmToJsFrame : public StubFrame {
1020 public:
1021 Type type() const override { return WASM_TO_JS; }
1022
1023 protected:
1024 inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);
1025
1026 private:
1027 friend class StackFrameIteratorBase;
1028};
1029
1030class JsToWasmFrame : public StubFrame {
1031 public:
1032 Type type() const override { return JS_TO_WASM; }
1033
1034 protected:
1035 inline explicit JsToWasmFrame(StackFrameIteratorBase* iterator);
1036
1037 private:
1038 friend class StackFrameIteratorBase;
1039};
1040
1041class CWasmEntryFrame : public StubFrame {
1042 public:
1043 Type type() const override { return C_WASM_ENTRY; }
1044
1045 protected:
1046 inline explicit CWasmEntryFrame(StackFrameIteratorBase* iterator);
1047
1048 private:
1049 friend class StackFrameIteratorBase;
1050};
1051
1052class WasmCompileLazyFrame : public StandardFrame {
1053 public:
1054 Type type() const override { return WASM_COMPILE_LAZY; }
1055
1056 Code unchecked_code() const override;
1057 WasmInstanceObject wasm_instance() const;
1058 FullObjectSlot wasm_instance_slot() const;
1059
1060 // Garbage collection support.
1061 void Iterate(RootVisitor* v) const override;
1062
1063 static WasmCompileLazyFrame* cast(StackFrame* frame) {
1064 DCHECK(frame->is_wasm_compile_lazy());
1065 return static_cast<WasmCompileLazyFrame*>(frame);
1066 }
1067
1068 protected:
1069 inline explicit WasmCompileLazyFrame(StackFrameIteratorBase* iterator);
1070
1071 Address GetCallerStackPointer() const override;
1072
1073 private:
1074 friend class StackFrameIteratorBase;
1075};
1076
1077class InternalFrame: public StandardFrame {
1078 public:
1079 Type type() const override { return INTERNAL; }
1080
1081 // Garbage collection support.
1082 void Iterate(RootVisitor* v) const override;
1083
1084 // Determine the code for the frame.
1085 Code unchecked_code() const override;
1086
1087 static InternalFrame* cast(StackFrame* frame) {
1088 DCHECK(frame->is_internal());
1089 return static_cast<InternalFrame*>(frame);
1090 }
1091
1092 protected:
1093 inline explicit InternalFrame(StackFrameIteratorBase* iterator);
1094
1095 Address GetCallerStackPointer() const override;
1096
1097 private:
1098 friend class StackFrameIteratorBase;
1099};
1100
1101
1102// Construct frames are special trampoline frames introduced to handle
1103// function invocations through 'new'.
1104class ConstructFrame: public InternalFrame {
1105 public:
1106 Type type() const override { return CONSTRUCT; }
1107
1108 static ConstructFrame* cast(StackFrame* frame) {
1109 DCHECK(frame->is_construct());
1110 return static_cast<ConstructFrame*>(frame);
1111 }
1112
1113 protected:
1114 inline explicit ConstructFrame(StackFrameIteratorBase* iterator);
1115
1116 private:
1117 friend class StackFrameIteratorBase;
1118};
1119
1120class BuiltinContinuationFrame : public InternalFrame {
1121 public:
1122 Type type() const override { return BUILTIN_CONTINUATION; }
1123
1124 static BuiltinContinuationFrame* cast(StackFrame* frame) {
1125 DCHECK(frame->is_builtin_continuation());
1126 return static_cast<BuiltinContinuationFrame*>(frame);
1127 }
1128
1129 protected:
1130 inline explicit BuiltinContinuationFrame(StackFrameIteratorBase* iterator);
1131
1132 private:
1133 friend class StackFrameIteratorBase;
1134};
1135
1136class JavaScriptBuiltinContinuationFrame : public JavaScriptFrame {
1137 public:
1138 Type type() const override { return JAVA_SCRIPT_BUILTIN_CONTINUATION; }
1139
1140 static JavaScriptBuiltinContinuationFrame* cast(StackFrame* frame) {
1141 DCHECK(frame->is_java_script_builtin_continuation());
1142 return static_cast<JavaScriptBuiltinContinuationFrame*>(frame);
1143 }
1144
1145 int ComputeParametersCount() const override;
1146 intptr_t GetSPToFPDelta() const;
1147
1148 Object context() const override;
1149
1150 protected:
1151 inline explicit JavaScriptBuiltinContinuationFrame(
1152 StackFrameIteratorBase* iterator);
1153
1154 private:
1155 friend class StackFrameIteratorBase;
1156};
1157
1158class JavaScriptBuiltinContinuationWithCatchFrame
1159 : public JavaScriptBuiltinContinuationFrame {
1160 public:
1161 Type type() const override {
1162 return JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH;
1163 }
1164
1165 static JavaScriptBuiltinContinuationWithCatchFrame* cast(StackFrame* frame) {
1166 DCHECK(frame->is_java_script_builtin_with_catch_continuation());
1167 return static_cast<JavaScriptBuiltinContinuationWithCatchFrame*>(frame);
1168 }
1169
1170 // Patch in the exception object at the appropriate location into the stack
1171 // frame.
1172 void SetException(Object exception);
1173
1174 protected:
1175 inline explicit JavaScriptBuiltinContinuationWithCatchFrame(
1176 StackFrameIteratorBase* iterator);
1177
1178 private:
1179 friend class StackFrameIteratorBase;
1180};
1181
1182class StackFrameIteratorBase {
1183 public:
1184 Isolate* isolate() const { return isolate_; }
1185
1186 bool done() const { return frame_ == nullptr; }
1187
1188 protected:
1189 // An iterator that iterates over a given thread's stack.
1190 StackFrameIteratorBase(Isolate* isolate, bool can_access_heap_objects);
1191
1192 Isolate* isolate_;
1193#define DECLARE_SINGLETON(ignore, type) type type##_;
1194 STACK_FRAME_TYPE_LIST(DECLARE_SINGLETON)
1195#undef DECLARE_SINGLETON
1196 StackFrame* frame_;
1197 StackHandler* handler_;
1198 const bool can_access_heap_objects_;
1199
1200 StackHandler* handler() const {
1201 DCHECK(!done());
1202 return handler_;
1203 }
1204
1205 // Get the type-specific frame singleton in a given state.
1206 StackFrame* SingletonFor(StackFrame::Type type, StackFrame::State* state);
1207 // A helper function, can return a nullptr pointer.
1208 StackFrame* SingletonFor(StackFrame::Type type);
1209
1210 private:
1211 friend class StackFrame;
1212 DISALLOW_COPY_AND_ASSIGN(StackFrameIteratorBase);
1213};
1214
1215
1216class StackFrameIterator: public StackFrameIteratorBase {
1217 public:
1218 // An iterator that iterates over the isolate's current thread's stack,
1219 V8_EXPORT_PRIVATE explicit StackFrameIterator(Isolate* isolate);
1220 // An iterator that iterates over a given thread's stack.
1221 V8_EXPORT_PRIVATE StackFrameIterator(Isolate* isolate, ThreadLocalTop* t);
1222
1223 StackFrame* frame() const {
1224 DCHECK(!done());
1225 return frame_;
1226 }
1227 V8_EXPORT_PRIVATE void Advance();
1228
1229 private:
1230 // Go back to the first frame.
1231 void Reset(ThreadLocalTop* top);
1232
1233 DISALLOW_COPY_AND_ASSIGN(StackFrameIterator);
1234};
1235
1236// Iterator that supports iterating through all JavaScript frames.
1237class JavaScriptFrameIterator {
1238 public:
1239 inline explicit JavaScriptFrameIterator(Isolate* isolate);
1240 inline JavaScriptFrameIterator(Isolate* isolate, ThreadLocalTop* top);
1241
1242 inline JavaScriptFrame* frame() const;
1243
1244 bool done() const { return iterator_.done(); }
1245 V8_EXPORT_PRIVATE void Advance();
1246 void AdvanceOneFrame() { iterator_.Advance(); }
1247
1248 private:
1249 StackFrameIterator iterator_;
1250};
1251
1252// NOTE: The stack trace frame iterator is an iterator that only traverse proper
1253// JavaScript frames that have proper JavaScript functions and WebAssembly
1254// frames.
1255class V8_EXPORT_PRIVATE StackTraceFrameIterator {
1256 public:
1257 explicit StackTraceFrameIterator(Isolate* isolate);
1258 // Skip frames until the frame with the given id is reached.
1259 StackTraceFrameIterator(Isolate* isolate, StackFrame::Id id);
1260 bool done() const { return iterator_.done(); }
1261 void Advance();
1262 void AdvanceOneFrame() { iterator_.Advance(); }
1263
1264 inline StandardFrame* frame() const;
1265
1266 inline bool is_javascript() const;
1267 inline bool is_wasm() const;
1268 inline JavaScriptFrame* javascript_frame() const;
1269
1270 private:
1271 StackFrameIterator iterator_;
1272 bool IsValidFrame(StackFrame* frame) const;
1273};
1274
1275class SafeStackFrameIterator: public StackFrameIteratorBase {
1276 public:
1277 SafeStackFrameIterator(Isolate* isolate,
1278 Address fp, Address sp,
1279 Address js_entry_sp);
1280
1281 inline StackFrame* frame() const;
1282 void Advance();
1283
1284 StackFrame::Type top_frame_type() const { return top_frame_type_; }
1285
1286 private:
1287 void AdvanceOneFrame();
1288
1289 bool IsValidStackAddress(Address addr) const {
1290 return low_bound_ <= addr && addr <= high_bound_;
1291 }
1292 bool IsValidFrame(StackFrame* frame) const;
1293 bool IsValidCaller(StackFrame* frame);
1294 bool IsValidExitFrame(Address fp) const;
1295 bool IsValidTop(ThreadLocalTop* top) const;
1296
1297 const Address low_bound_;
1298 const Address high_bound_;
1299 StackFrame::Type top_frame_type_;
1300 ExternalCallbackScope* external_callback_scope_;
1301};
1302} // namespace internal
1303} // namespace v8
1304
1305#endif // V8_FRAMES_H_
1306