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