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