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