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 : #include "src/frames.h"
6 :
7 : #include <memory>
8 : #include <sstream>
9 :
10 : #include "src/base/bits.h"
11 : #include "src/deoptimizer.h"
12 : #include "src/frames-inl.h"
13 : #include "src/ic/ic-stats.h"
14 : #include "src/register-configuration.h"
15 : #include "src/safepoint-table.h"
16 : #include "src/string-stream.h"
17 : #include "src/visitors.h"
18 : #include "src/vm-state-inl.h"
19 : #include "src/wasm/wasm-objects-inl.h"
20 :
21 : namespace v8 {
22 : namespace internal {
23 :
24 : ReturnAddressLocationResolver StackFrame::return_address_location_resolver_ =
25 : nullptr;
26 :
27 : // Iterator that supports traversing the stack handlers of a
28 : // particular frame. Needs to know the top of the handler chain.
29 : class StackHandlerIterator BASE_EMBEDDED {
30 : public:
31 52900959 : StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
32 : : limit_(frame->fp()), handler_(handler) {
33 : // Make sure the handler has already been unwound to this frame.
34 : DCHECK(frame->sp() <= handler->address());
35 : }
36 :
37 : StackHandler* handler() const { return handler_; }
38 :
39 54288701 : bool done() { return handler_ == nullptr || handler_->address() > limit_; }
40 : void Advance() {
41 : DCHECK(!done());
42 : handler_ = handler_->next();
43 : }
44 :
45 : private:
46 : const Address limit_;
47 : StackHandler* handler_;
48 : };
49 :
50 :
51 : // -------------------------------------------------------------------------
52 :
53 :
54 : #define INITIALIZE_SINGLETON(type, field) field##_(this),
55 10905745 : StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
56 : bool can_access_heap_objects)
57 : : isolate_(isolate),
58 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) frame_(nullptr),
59 : handler_(nullptr),
60 21811490 : can_access_heap_objects_(can_access_heap_objects) {}
61 : #undef INITIALIZE_SINGLETON
62 :
63 10367203 : StackFrameIterator::StackFrameIterator(Isolate* isolate)
64 20734406 : : StackFrameIterator(isolate, isolate->thread_local_top()) {}
65 :
66 507709 : StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
67 10874912 : : StackFrameIteratorBase(isolate, true) {
68 10874911 : Reset(t);
69 507709 : }
70 :
71 52900952 : void StackFrameIterator::Advance() {
72 : DCHECK(!done());
73 : // Compute the state of the calling frame before restoring
74 : // callee-saved registers and unwinding handlers. This allows the
75 : // frame code that computes the caller state to access the top
76 : // handler and the value of any callee-saved register if needed.
77 52900952 : StackFrame::State state;
78 52900952 : StackFrame::Type type = frame_->GetCallerState(&state);
79 :
80 : // Unwind handlers corresponding to the current frame.
81 52900959 : StackHandlerIterator it(frame_, handler_);
82 54288701 : while (!it.done()) it.Advance();
83 52900959 : handler_ = it.handler();
84 :
85 : // Advance to the calling frame.
86 52900959 : frame_ = SingletonFor(type, &state);
87 :
88 : // When we're done iterating over the stack frames, the handler
89 : // chain must have been completely unwound.
90 : DCHECK(!done() || handler_ == nullptr);
91 52900958 : }
92 :
93 :
94 32624736 : void StackFrameIterator::Reset(ThreadLocalTop* top) {
95 10874912 : StackFrame::State state;
96 : StackFrame::Type type = ExitFrame::GetStateForFramePointer(
97 10874912 : Isolate::c_entry_fp(top), &state);
98 10874912 : handler_ = StackHandler::FromAddress(Isolate::handler(top));
99 10874912 : frame_ = SingletonFor(type, &state);
100 10874912 : }
101 :
102 :
103 63931278 : StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
104 : StackFrame::State* state) {
105 63931278 : StackFrame* result = SingletonFor(type);
106 : DCHECK((!result) == (type == StackFrame::NONE));
107 63931273 : if (result) result->state_ = *state;
108 63931273 : return result;
109 : }
110 :
111 :
112 64056841 : StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
113 : #define FRAME_TYPE_CASE(type, field) \
114 : case StackFrame::type: \
115 : return &field##_;
116 :
117 64056841 : switch (type) {
118 : case StackFrame::NONE:
119 : return nullptr;
120 1508987 : STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
121 : default: break;
122 : }
123 : return nullptr;
124 :
125 : #undef FRAME_TYPE_CASE
126 : }
127 :
128 : // -------------------------------------------------------------------------
129 :
130 1351765 : void JavaScriptFrameIterator::Advance() {
131 2212657 : do {
132 2212657 : iterator_.Advance();
133 2212657 : } while (!iterator_.done() && !iterator_.frame()->is_java_script());
134 1351765 : }
135 :
136 : // -------------------------------------------------------------------------
137 :
138 1767337 : StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
139 1767337 : : iterator_(isolate) {
140 1767337 : if (!done() && !IsValidFrame(iterator_.frame())) Advance();
141 1767337 : }
142 :
143 158339 : StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate,
144 : StackFrame::Id id)
145 158339 : : StackTraceFrameIterator(isolate) {
146 1561697 : while (!done() && frame()->id() != id) Advance();
147 158339 : }
148 :
149 3062865 : void StackTraceFrameIterator::Advance() {
150 6092418 : do {
151 6092418 : iterator_.Advance();
152 6092418 : } while (!done() && !IsValidFrame(iterator_.frame()));
153 3062865 : }
154 :
155 7620675 : bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
156 7620675 : if (frame->is_java_script()) {
157 : JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame);
158 6449812 : if (!jsFrame->function()->IsJSFunction()) return false;
159 6449812 : return jsFrame->function()->shared()->IsSubjectToDebugging();
160 : }
161 : // apart from javascript, only wasm is valid
162 4395769 : return frame->is_wasm();
163 : }
164 :
165 : // -------------------------------------------------------------------------
166 :
167 : namespace {
168 :
169 127412 : bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
170 : Code* interpreter_entry_trampoline =
171 : isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
172 : Code* interpreter_bytecode_advance =
173 : isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeAdvance);
174 : Code* interpreter_bytecode_dispatch =
175 : isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
176 :
177 252149 : return (pc >= interpreter_entry_trampoline->instruction_start() &&
178 12347 : pc < interpreter_entry_trampoline->instruction_end()) ||
179 22019 : (pc >= interpreter_bytecode_advance->instruction_start() &&
180 139759 : pc < interpreter_bytecode_advance->instruction_end()) ||
181 22019 : (pc >= interpreter_bytecode_dispatch->instruction_start() &&
182 127412 : pc < interpreter_bytecode_dispatch->instruction_end());
183 : }
184 :
185 : DISABLE_ASAN Address ReadMemoryAt(Address address) {
186 12523 : return Memory::Address_at(address);
187 : }
188 :
189 : } // namespace
190 :
191 30835 : SafeStackFrameIterator::SafeStackFrameIterator(
192 30835 : Isolate* isolate,
193 26017 : Address fp, Address sp, Address js_entry_sp)
194 : : StackFrameIteratorBase(isolate, false),
195 : low_bound_(sp),
196 : high_bound_(js_entry_sp),
197 : top_frame_type_(StackFrame::NONE),
198 61670 : external_callback_scope_(isolate->external_callback_scope()) {
199 30835 : StackFrame::State state;
200 : StackFrame::Type type;
201 48176 : ThreadLocalTop* top = isolate->thread_local_top();
202 : bool advance_frame = true;
203 30835 : if (IsValidTop(top)) {
204 17341 : type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
205 17341 : top_frame_type_ = type;
206 13494 : } else if (IsValidStackAddress(fp)) {
207 : DCHECK_NOT_NULL(fp);
208 12523 : state.fp = fp;
209 12523 : state.sp = sp;
210 : state.pc_address = StackFrame::ResolveReturnAddressLocation(
211 25046 : reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
212 :
213 : // If the top of stack is a return address to the interpreter trampoline,
214 : // then we are likely in a bytecode handler with elided frame. In that
215 : // case, set the PC properly and make sure we do not drop the frame.
216 12523 : if (IsValidStackAddress(sp)) {
217 : MSAN_MEMORY_IS_INITIALIZED(sp, kPointerSize);
218 : Address tos = ReadMemoryAt(reinterpret_cast<Address>(sp));
219 12523 : if (IsInterpreterFramePc(isolate, tos)) {
220 7327 : state.pc_address = reinterpret_cast<Address*>(sp);
221 : advance_frame = false;
222 : }
223 : }
224 :
225 : // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
226 : // we check only that kMarkerOffset is within the stack bounds and do
227 : // compile time check that kContextOffset slot is pushed on the stack before
228 : // kMarkerOffset.
229 : STATIC_ASSERT(StandardFrameConstants::kFunctionOffset <
230 : StandardFrameConstants::kContextOffset);
231 12523 : Address frame_marker = fp + StandardFrameConstants::kFunctionOffset;
232 12523 : if (IsValidStackAddress(frame_marker)) {
233 12266 : type = StackFrame::ComputeType(this, &state);
234 12266 : top_frame_type_ = type;
235 : // We only keep the top frame if we believe it to be interpreted frame.
236 12266 : if (type != StackFrame::INTERPRETED) {
237 : advance_frame = true;
238 : }
239 : } else {
240 : // Mark the frame as OPTIMIZED if we cannot determine its type.
241 : // We chose OPTIMIZED rather than INTERPRETED because it's closer to
242 : // the original value of StackFrame::JAVA_SCRIPT here, in that JAVA_SCRIPT
243 : // referred to full-codegen frames (now removed from the tree), and
244 : // OPTIMIZED refers to turbofan frames, both of which are generated
245 : // code. INTERPRETED frames refer to bytecode.
246 : // The frame anyways will be skipped.
247 : type = StackFrame::OPTIMIZED;
248 : // Top frame is incomplete so we cannot reliably determine its type.
249 257 : top_frame_type_ = StackFrame::NONE;
250 : }
251 : } else {
252 971 : return;
253 : }
254 29864 : frame_ = SingletonFor(type, &state);
255 29864 : if (advance_frame && frame_) Advance();
256 : }
257 :
258 :
259 48176 : bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
260 : Address c_entry_fp = Isolate::c_entry_fp(top);
261 30835 : if (!IsValidExitFrame(c_entry_fp)) return false;
262 : // There should be at least one JS_ENTRY stack handler.
263 : Address handler = Isolate::handler(top);
264 17341 : if (handler == nullptr) return false;
265 : // Check that there are no js frames on top of the native frames.
266 17341 : return c_entry_fp < handler;
267 : }
268 :
269 :
270 155423 : void SafeStackFrameIterator::AdvanceOneFrame() {
271 : DCHECK(!done());
272 155423 : StackFrame* last_frame = frame_;
273 : Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
274 : // Before advancing to the next stack frame, perform pointer validity tests.
275 155423 : if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
276 29858 : frame_ = nullptr;
277 59716 : return;
278 : }
279 :
280 : // Advance to the previous frame.
281 125565 : StackFrame::State state;
282 376695 : StackFrame::Type type = frame_->GetCallerState(&state);
283 125565 : frame_ = SingletonFor(type, &state);
284 125565 : if (!frame_) return;
285 :
286 : // Check that we have actually moved to the previous frame in the stack.
287 251130 : if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
288 0 : frame_ = nullptr;
289 : }
290 : }
291 :
292 :
293 155423 : bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
294 310846 : return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
295 : }
296 :
297 :
298 310912 : bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
299 155423 : StackFrame::State state;
300 280922 : if (frame->is_entry() || frame->is_construct_entry()) {
301 : // See EntryFrame::GetCallerState. It computes the caller FP address
302 : // and calls ExitFrame::GetStateForFramePointer on it. We need to be
303 : // sure that caller FP address is valid.
304 : Address caller_fp = Memory::Address_at(
305 29924 : frame->fp() + EntryFrameConstants::kCallerFPOffset);
306 29924 : if (!IsValidExitFrame(caller_fp)) return false;
307 125499 : } else if (frame->is_arguments_adaptor()) {
308 : // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
309 : // the number of arguments is stored on stack as Smi. We need to check
310 : // that it really an Smi.
311 : Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
312 16 : GetExpression(0);
313 16 : if (!number_of_args->IsSmi()) {
314 : return false;
315 : }
316 : }
317 125565 : frame->ComputeCallerState(&state);
318 502260 : return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
319 251130 : SingletonFor(frame->GetCallerState(&state)) != nullptr;
320 : }
321 :
322 :
323 60759 : bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
324 60759 : if (!IsValidStackAddress(fp)) return false;
325 : Address sp = ExitFrame::ComputeStackPointer(fp);
326 17416 : if (!IsValidStackAddress(sp)) return false;
327 : StackFrame::State state;
328 : ExitFrame::FillState(fp, sp, &state);
329 : MSAN_MEMORY_IS_INITIALIZED(state.pc_address, sizeof(state.pc_address));
330 17407 : return *state.pc_address != nullptr;
331 : }
332 :
333 :
334 83642 : void SafeStackFrameIterator::Advance() {
335 : while (true) {
336 155423 : AdvanceOneFrame();
337 155423 : if (done()) break;
338 : ExternalCallbackScope* last_callback_scope = nullptr;
339 159781 : while (external_callback_scope_ != nullptr &&
340 17230 : external_callback_scope_->scope_address() < frame_->fp()) {
341 : // As long as the setup of a frame is not atomic, we may happen to be
342 : // in an interval where an ExternalCallbackScope is already created,
343 : // but the frame is not yet entered. So we are actually observing
344 : // the previous frame.
345 : // Skip all the ExternalCallbackScope's that are below the current fp.
346 : last_callback_scope = external_callback_scope_;
347 16986 : external_callback_scope_ = external_callback_scope_->previous();
348 : }
349 125565 : if (frame_->is_java_script()) break;
350 215475 : if (frame_->is_exit() || frame_->is_builtin_exit()) {
351 : // Some of the EXIT frames may have ExternalCallbackScope allocated on
352 : // top of them. In that case the scope corresponds to the first EXIT
353 : // frame beneath it. There may be other EXIT frames on top of the
354 : // ExternalCallbackScope, just skip them as we cannot collect any useful
355 : // information about them.
356 66 : if (last_callback_scope) {
357 : frame_->state_.pc_address =
358 132 : last_callback_scope->callback_entrypoint_address();
359 : }
360 : break;
361 : }
362 : }
363 83642 : }
364 :
365 :
366 : // -------------------------------------------------------------------------
367 :
368 : namespace {
369 63282657 : Code* GetContainingCode(Isolate* isolate, Address pc) {
370 63282657 : return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code;
371 : }
372 : } // namespace
373 :
374 16455506 : Code* StackFrame::LookupCode() const {
375 : Code* result = GetContainingCode(isolate(), pc());
376 : DCHECK_GE(pc(), result->instruction_start());
377 : DCHECK_LT(pc(), result->instruction_end());
378 4769472 : return result;
379 : }
380 :
381 : #ifdef DEBUG
382 : static bool GcSafeCodeContains(HeapObject* object, Address addr);
383 : #endif
384 :
385 0 : void StackFrame::IteratePc(RootVisitor* v, Address* pc_address,
386 : Address* constant_pool_address, Code* holder) {
387 2863636 : Address pc = *pc_address;
388 : DCHECK(GcSafeCodeContains(holder, pc));
389 2863636 : unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
390 2863636 : Object* code = holder;
391 2863636 : v->VisitRootPointer(Root::kTop, &code);
392 5727272 : if (code == holder) return;
393 : holder = reinterpret_cast<Code*>(code);
394 0 : pc = holder->instruction_start() + pc_offset;
395 0 : *pc_address = pc;
396 : if (FLAG_enable_embedded_constant_pool && constant_pool_address) {
397 : *constant_pool_address = holder->constant_pool();
398 : }
399 : }
400 :
401 :
402 0 : void StackFrame::SetReturnAddressLocationResolver(
403 : ReturnAddressLocationResolver resolver) {
404 : DCHECK_NULL(return_address_location_resolver_);
405 0 : return_address_location_resolver_ = resolver;
406 0 : }
407 :
408 103404591 : StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
409 : State* state) {
410 : DCHECK_NOT_NULL(state->fp);
411 :
412 : MSAN_MEMORY_IS_INITIALIZED(
413 : state->fp + CommonFrameConstants::kContextOrFrameTypeOffset,
414 : kPointerSize);
415 : intptr_t marker = Memory::intptr_at(
416 51776483 : state->fp + CommonFrameConstants::kContextOrFrameTypeOffset);
417 51776483 : if (!iterator->can_access_heap_objects_) {
418 : // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really
419 : // means that we are being called from the profiler, which can interrupt
420 : // the VM with a signal at any arbitrary instruction, with essentially
421 : // anything on the stack. So basically none of these checks are 100%
422 : // reliable.
423 : MSAN_MEMORY_IS_INITIALIZED(
424 : state->fp + StandardFrameConstants::kFunctionOffset, kPointerSize);
425 : Object* maybe_function =
426 263264 : Memory::Object_at(state->fp + StandardFrameConstants::kFunctionOffset);
427 263264 : if (!StackFrame::IsTypeMarker(marker)) {
428 114889 : if (maybe_function->IsSmi()) {
429 : return NONE;
430 114889 : } else if (IsInterpreterFramePc(iterator->isolate(),
431 114889 : *(state->pc_address))) {
432 : return INTERPRETED;
433 : } else {
434 7149 : return OPTIMIZED;
435 : }
436 : }
437 : } else {
438 : // Look up the code object to figure out the type of the stack frame.
439 : Code* code_obj =
440 51513219 : GetContainingCode(iterator->isolate(), *(state->pc_address));
441 51513220 : if (code_obj != nullptr) {
442 51513220 : switch (code_obj->kind()) {
443 : case Code::BUILTIN:
444 33483069 : if (StackFrame::IsTypeMarker(marker)) break;
445 29076636 : if (code_obj->is_interpreter_trampoline_builtin()) {
446 : return INTERPRETED;
447 : }
448 621931 : if (code_obj->is_turbofanned()) {
449 : // TODO(bmeurer): We treat frames for BUILTIN Code objects as
450 : // OptimizedFrame for now (all the builtins with JavaScript
451 : // linkage are actually generated with TurboFan currently, so
452 : // this is sound).
453 : return OPTIMIZED;
454 : }
455 28 : return BUILTIN;
456 : case Code::OPTIMIZED_FUNCTION:
457 : return OPTIMIZED;
458 : case Code::WASM_FUNCTION:
459 2900909 : return WASM_COMPILED;
460 : case Code::WASM_TO_JS_FUNCTION:
461 7303 : return WASM_TO_JS;
462 : case Code::JS_TO_WASM_FUNCTION:
463 94745 : return JS_TO_WASM;
464 : case Code::WASM_INTERPRETER_ENTRY:
465 49145 : return WASM_INTERPRETER_ENTRY;
466 : case Code::C_WASM_ENTRY:
467 80 : return C_WASM_ENTRY;
468 : default:
469 : // All other types should have an explicit marker
470 : break;
471 : }
472 : } else {
473 : return NONE;
474 : }
475 : }
476 :
477 : DCHECK(StackFrame::IsTypeMarker(marker));
478 : StackFrame::Type candidate = StackFrame::MarkerToType(marker);
479 13726535 : switch (candidate) {
480 : case ENTRY:
481 : case CONSTRUCT_ENTRY:
482 : case EXIT:
483 : case BUILTIN_CONTINUATION:
484 : case JAVA_SCRIPT_BUILTIN_CONTINUATION:
485 : case BUILTIN_EXIT:
486 : case STUB:
487 : case INTERNAL:
488 : case CONSTRUCT:
489 : case ARGUMENTS_ADAPTOR:
490 : case WASM_TO_JS:
491 : case WASM_COMPILED:
492 : return candidate;
493 : case JS_TO_WASM:
494 : case OPTIMIZED:
495 : case INTERPRETED:
496 : default:
497 : // Unoptimized and optimized JavaScript frames, including
498 : // interpreted frames, should never have a StackFrame::Type
499 : // marker. If we find one, we're likely being called from the
500 : // profiler in a bogus stack frame.
501 : return NONE;
502 : }
503 : }
504 :
505 :
506 : #ifdef DEBUG
507 : bool StackFrame::can_access_heap_objects() const {
508 : return iterator_->can_access_heap_objects_;
509 : }
510 : #endif
511 :
512 :
513 51764217 : StackFrame::Type StackFrame::GetCallerState(State* state) const {
514 51764217 : ComputeCallerState(state);
515 51764214 : return ComputeType(iterator_, state);
516 : }
517 :
518 :
519 0 : Address StackFrame::UnpaddedFP() const {
520 0 : return fp();
521 : }
522 :
523 :
524 0 : Code* EntryFrame::unchecked_code() const {
525 0 : return isolate()->heap()->js_entry_code();
526 : }
527 :
528 :
529 66 : void EntryFrame::ComputeCallerState(State* state) const {
530 66 : GetCallerState(state);
531 66 : }
532 :
533 :
534 1387940 : StackFrame::Type EntryFrame::GetCallerState(State* state) const {
535 : const int offset = EntryFrameConstants::kCallerFPOffset;
536 1387940 : Address fp = Memory::Address_at(this->fp() + offset);
537 1387940 : return ExitFrame::GetStateForFramePointer(fp, state);
538 : }
539 :
540 0 : Code* ConstructEntryFrame::unchecked_code() const {
541 0 : return isolate()->heap()->js_construct_entry_code();
542 : }
543 :
544 :
545 0 : Object*& ExitFrame::code_slot() const {
546 : const int offset = ExitFrameConstants::kCodeOffset;
547 119488 : return Memory::Object_at(fp() + offset);
548 : }
549 :
550 0 : Code* ExitFrame::unchecked_code() const {
551 0 : return reinterpret_cast<Code*>(code_slot());
552 : }
553 :
554 :
555 10701167 : void ExitFrame::ComputeCallerState(State* state) const {
556 : // Set up the caller state.
557 32103497 : state->sp = caller_sp();
558 10701165 : state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
559 : state->pc_address = ResolveReturnAddressLocation(
560 21402330 : reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
561 10701165 : state->callee_pc_address = nullptr;
562 : if (FLAG_enable_embedded_constant_pool) {
563 : state->constant_pool_address = reinterpret_cast<Address*>(
564 : fp() + ExitFrameConstants::kConstantPoolOffset);
565 : }
566 10701165 : }
567 :
568 :
569 119488 : void ExitFrame::Iterate(RootVisitor* v) const {
570 : // The arguments are traversed as part of the expression stack of
571 : // the calling frame.
572 119488 : IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
573 238976 : v->VisitRootPointer(Root::kTop, &code_slot());
574 119488 : }
575 :
576 :
577 10702242 : Address ExitFrame::GetCallerStackPointer() const {
578 10702242 : return fp() + ExitFrameConstants::kCallerSPOffset;
579 : }
580 :
581 :
582 12280192 : StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
583 12280192 : if (fp == 0) return NONE;
584 : Address sp = ComputeStackPointer(fp);
585 : FillState(fp, sp, state);
586 : DCHECK_NOT_NULL(*state->pc_address);
587 :
588 10666571 : return ComputeFrameType(fp);
589 : }
590 :
591 0 : StackFrame::Type ExitFrame::ComputeFrameType(Address fp) {
592 : // Distinguish between between regular and builtin exit frames.
593 : // Default to EXIT in all hairy cases (e.g., when called from profiler).
594 : const int offset = ExitFrameConstants::kFrameTypeOffset;
595 10666571 : Object* marker = Memory::Object_at(fp + offset);
596 :
597 10666571 : if (!marker->IsSmi()) {
598 : return EXIT;
599 : }
600 :
601 : intptr_t marker_int = bit_cast<intptr_t>(marker);
602 :
603 10666571 : StackFrame::Type frame_type = static_cast<StackFrame::Type>(marker_int >> 1);
604 10666571 : if (frame_type == EXIT || frame_type == BUILTIN_EXIT) {
605 0 : return frame_type;
606 : }
607 :
608 : return EXIT;
609 : }
610 :
611 0 : Address ExitFrame::ComputeStackPointer(Address fp) {
612 : MSAN_MEMORY_IS_INITIALIZED(fp + ExitFrameConstants::kSPOffset, kPointerSize);
613 10683987 : return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
614 : }
615 :
616 0 : void ExitFrame::FillState(Address fp, Address sp, State* state) {
617 10666571 : state->sp = sp;
618 10666571 : state->fp = fp;
619 : state->pc_address = ResolveReturnAddressLocation(
620 21350549 : reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
621 10666571 : state->callee_pc_address = nullptr;
622 : // The constant pool recorded in the exit frame is not associated
623 : // with the pc in this state (the return address into a C entry
624 : // stub). ComputeCallerState will retrieve the constant pool
625 : // together with the associated caller pc.
626 10666571 : state->constant_pool_address = nullptr;
627 0 : }
628 :
629 68416 : JSFunction* BuiltinExitFrame::function() const {
630 68416 : return JSFunction::cast(target_slot_object());
631 : }
632 :
633 74870 : Object* BuiltinExitFrame::receiver() const { return receiver_slot_object(); }
634 :
635 37445 : bool BuiltinExitFrame::IsConstructor() const {
636 74890 : return !new_target_slot_object()->IsUndefined(isolate());
637 : }
638 :
639 0 : Object* BuiltinExitFrame::GetParameter(int i) const {
640 : DCHECK(i >= 0 && i < ComputeParametersCount());
641 : int offset =
642 10 : BuiltinExitFrameConstants::kFirstArgumentOffset + i * kPointerSize;
643 10 : return Memory::Object_at(fp() + offset);
644 : }
645 :
646 0 : int BuiltinExitFrame::ComputeParametersCount() const {
647 : Object* argc_slot = argc_slot_object();
648 : DCHECK(argc_slot->IsSmi());
649 : // Argc also counts the receiver, target, new target, and argc itself as args,
650 : // therefore the real argument count is argc - 4.
651 10 : int argc = Smi::ToInt(argc_slot) - 4;
652 : DCHECK_GE(argc, 0);
653 0 : return argc;
654 : }
655 :
656 : namespace {
657 : void PrintIndex(StringStream* accumulator, StackFrame::PrintMode mode,
658 : int index) {
659 20 : accumulator->Add((mode == StackFrame::OVERVIEW) ? "%5d: " : "[%d]: ", index);
660 : }
661 : } // namespace
662 :
663 10 : void BuiltinExitFrame::Print(StringStream* accumulator, PrintMode mode,
664 : int index) const {
665 : DisallowHeapAllocation no_gc;
666 : Object* receiver = this->receiver();
667 : JSFunction* function = this->function();
668 :
669 10 : accumulator->PrintSecurityTokenIfChanged(function);
670 : PrintIndex(accumulator, mode, index);
671 10 : accumulator->Add("builtin exit frame: ");
672 10 : Code* code = nullptr;
673 10 : if (IsConstructor()) accumulator->Add("new ");
674 10 : accumulator->PrintFunction(function, receiver, &code);
675 :
676 10 : accumulator->Add("(this=%o", receiver);
677 :
678 : // Print the parameters.
679 : int parameters_count = ComputeParametersCount();
680 20 : for (int i = 0; i < parameters_count; i++) {
681 10 : accumulator->Add(",%o", GetParameter(i));
682 : }
683 :
684 10 : accumulator->Add(")\n\n");
685 10 : }
686 :
687 1782647 : Address StandardFrame::GetExpressionAddress(int n) const {
688 : const int offset = StandardFrameConstants::kExpressionsOffset;
689 1782647 : return fp() + offset - n * kPointerSize;
690 : }
691 :
692 39310785 : Address InterpretedFrame::GetExpressionAddress(int n) const {
693 : const int offset = InterpreterFrameConstants::kExpressionsOffset;
694 39310785 : return fp() + offset - n * kPointerSize;
695 : }
696 :
697 0 : Script* StandardFrame::script() const {
698 : // This should only be called on frames which override this method.
699 : DCHECK(false);
700 0 : return nullptr;
701 : }
702 :
703 0 : Object* StandardFrame::receiver() const {
704 0 : return isolate()->heap()->undefined_value();
705 : }
706 :
707 222 : Object* StandardFrame::context() const {
708 222 : return isolate()->heap()->undefined_value();
709 : }
710 :
711 0 : int StandardFrame::position() const {
712 : AbstractCode* code = AbstractCode::cast(LookupCode());
713 0 : int code_offset = static_cast<int>(pc() - code->instruction_start());
714 0 : return code->SourcePosition(code_offset);
715 : }
716 :
717 0 : int StandardFrame::ComputeExpressionsCount() const {
718 0 : Address base = GetExpressionAddress(0);
719 0 : Address limit = sp() - kPointerSize;
720 : DCHECK(base >= limit); // stack grows downwards
721 : // Include register-allocated locals in number of expressions.
722 0 : return static_cast<int>((base - limit) / kPointerSize);
723 : }
724 :
725 0 : Object* StandardFrame::GetParameter(int index) const {
726 : // StandardFrame does not define any parameters.
727 0 : UNREACHABLE();
728 : }
729 :
730 0 : int StandardFrame::ComputeParametersCount() const { return 0; }
731 :
732 41188557 : void StandardFrame::ComputeCallerState(State* state) const {
733 205942785 : state->sp = caller_sp();
734 41188557 : state->fp = caller_fp();
735 : state->pc_address = ResolveReturnAddressLocation(
736 82377114 : reinterpret_cast<Address*>(ComputePCAddress(fp())));
737 41188557 : state->callee_pc_address = pc_address();
738 : state->constant_pool_address =
739 41188557 : reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
740 41188557 : }
741 :
742 :
743 0 : bool StandardFrame::IsConstructor() const { return false; }
744 :
745 0 : void StandardFrame::Summarize(std::vector<FrameSummary>* functions) const {
746 : // This should only be called on frames which override this method.
747 0 : UNREACHABLE();
748 : }
749 :
750 604927 : void StandardFrame::IterateCompiledFrame(RootVisitor* v) const {
751 : // Make sure that we're not doing "safe" stack frame iteration. We cannot
752 : // possibly find pointers in optimized frames in that state.
753 : DCHECK(can_access_heap_objects());
754 :
755 : // Find the code and compute the safepoint information.
756 2419708 : Address inner_pointer = pc();
757 : InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
758 604927 : isolate()->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
759 604927 : if (!entry->safepoint_entry.is_valid()) {
760 42420 : entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
761 : DCHECK(entry->safepoint_entry.is_valid());
762 : } else {
763 : DCHECK(entry->safepoint_entry.Equals(
764 : entry->code->GetSafepointEntry(inner_pointer)));
765 : }
766 :
767 604927 : Code* code = entry->code;
768 604927 : SafepointEntry safepoint_entry = entry->safepoint_entry;
769 : unsigned stack_slots = code->stack_slots();
770 604927 : unsigned slot_space = stack_slots * kPointerSize;
771 :
772 : // Determine the fixed header and spill slot area size.
773 : int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp;
774 : intptr_t marker =
775 604927 : Memory::intptr_at(fp() + CommonFrameConstants::kContextOrFrameTypeOffset);
776 604927 : if (StackFrame::IsTypeMarker(marker)) {
777 : StackFrame::Type candidate = StackFrame::MarkerToType(marker);
778 79124 : switch (candidate) {
779 : case ENTRY:
780 : case CONSTRUCT_ENTRY:
781 : case EXIT:
782 : case BUILTIN_CONTINUATION:
783 : case JAVA_SCRIPT_BUILTIN_CONTINUATION:
784 : case BUILTIN_EXIT:
785 : case ARGUMENTS_ADAPTOR:
786 : case STUB:
787 : case INTERNAL:
788 : case CONSTRUCT:
789 : case JS_TO_WASM:
790 : case WASM_TO_JS:
791 : case WASM_COMPILED:
792 : case WASM_INTERPRETER_ENTRY:
793 : case C_WASM_ENTRY:
794 : frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
795 79124 : break;
796 : case OPTIMIZED:
797 : case INTERPRETED:
798 : case BUILTIN:
799 : // These frame types have a context, but they are actually stored
800 : // in the place on the stack that one finds the frame type.
801 0 : UNREACHABLE();
802 : break;
803 : case NONE:
804 : case NUMBER_OF_TYPES:
805 : case MANUAL:
806 0 : UNREACHABLE();
807 : break;
808 : }
809 : }
810 : slot_space -=
811 604927 : (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp);
812 :
813 604927 : Object** frame_header_base = &Memory::Object_at(fp() - frame_header_size);
814 : Object** frame_header_limit =
815 : &Memory::Object_at(fp() - StandardFrameConstants::kCPSlotSize);
816 : Object** parameters_base = &Memory::Object_at(sp());
817 604927 : Object** parameters_limit = frame_header_base - slot_space / kPointerSize;
818 :
819 : // Visit the parameters that may be on top of the saved registers.
820 1209854 : if (safepoint_entry.argument_count() > 0) {
821 : v->VisitRootPointers(Root::kTop, parameters_base,
822 0 : parameters_base + safepoint_entry.argument_count());
823 0 : parameters_base += safepoint_entry.argument_count();
824 : }
825 :
826 : // Skip saved double registers.
827 1209854 : if (safepoint_entry.has_doubles()) {
828 : // Number of doubles not known at snapshot time.
829 : DCHECK(!isolate()->serializer_enabled());
830 0 : parameters_base +=
831 : RegisterConfiguration::Default()->num_allocatable_double_registers() *
832 0 : kDoubleSize / kPointerSize;
833 : }
834 :
835 : // Visit the registers that contain pointers if any.
836 604927 : if (safepoint_entry.HasRegisters()) {
837 0 : for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
838 0 : if (safepoint_entry.HasRegisterAt(i)) {
839 : int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
840 0 : v->VisitRootPointer(Root::kTop, parameters_base + reg_stack_index);
841 : }
842 : }
843 : // Skip the words containing the register values.
844 0 : parameters_base += kNumSafepointRegisters;
845 : }
846 :
847 : // We're done dealing with the register bits.
848 604927 : uint8_t* safepoint_bits = safepoint_entry.bits();
849 604927 : safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
850 :
851 : // Visit the rest of the parameters if they are tagged.
852 604927 : if (code->has_tagged_params()) {
853 592087 : v->VisitRootPointers(Root::kTop, parameters_base, parameters_limit);
854 : }
855 :
856 : // Visit pointer spill slots and locals.
857 3641487 : for (unsigned index = 0; index < stack_slots; index++) {
858 3641487 : int byte_index = index >> kBitsPerByteLog2;
859 3641487 : int bit_index = index & (kBitsPerByte - 1);
860 3641487 : if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
861 295484 : v->VisitRootPointer(Root::kTop, parameters_limit + index);
862 : }
863 : }
864 :
865 : // Visit the return address in the callee and incoming arguments.
866 : IteratePc(v, pc_address(), constant_pool_address(), code);
867 :
868 1808324 : if (!is_wasm() && !is_wasm_to_js()) {
869 : // If this frame has JavaScript ABI, visit the context (in stub and JS
870 : // frames) and the function (in JS frames).
871 592192 : v->VisitRootPointers(Root::kTop, frame_header_base, frame_header_limit);
872 : }
873 604927 : }
874 :
875 79053 : void StubFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); }
876 :
877 0 : Code* StubFrame::unchecked_code() const {
878 0 : return isolate()->FindCodeObject(pc());
879 : }
880 :
881 :
882 8105952 : Address StubFrame::GetCallerStackPointer() const {
883 8105952 : return fp() + ExitFrameConstants::kCallerSPOffset;
884 : }
885 :
886 :
887 0 : int StubFrame::GetNumberOfIncomingArguments() const {
888 0 : return 0;
889 : }
890 :
891 55 : int StubFrame::LookupExceptionHandlerInTable(int* stack_slots) {
892 : Code* code = LookupCode();
893 : DCHECK(code->is_turbofanned());
894 : DCHECK_EQ(code->kind(), Code::BUILTIN);
895 : HandlerTable* table = HandlerTable::cast(code->handler_table());
896 55 : int pc_offset = static_cast<int>(pc() - code->entry());
897 55 : *stack_slots = code->stack_slots();
898 55 : return table->LookupReturn(pc_offset);
899 : }
900 :
901 519417 : void OptimizedFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); }
902 :
903 2076 : void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
904 2076 : Memory::Object_at(GetParameterSlot(index)) = value;
905 2076 : }
906 :
907 :
908 6830996 : bool JavaScriptFrame::IsConstructor() const {
909 : Address fp = caller_fp();
910 6830996 : if (has_adapted_arguments()) {
911 : // Skip the arguments adaptor frame and look at the real caller.
912 701951 : fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
913 : }
914 6830996 : return IsConstructFrame(fp);
915 : }
916 :
917 :
918 0 : bool JavaScriptFrame::HasInlinedFrames() const {
919 : std::vector<SharedFunctionInfo*> functions;
920 0 : GetFunctions(&functions);
921 0 : return functions.size() > 1;
922 : }
923 :
924 :
925 8 : int JavaScriptFrame::GetArgumentsLength() const {
926 : // If there is an arguments adaptor frame get the arguments length from it.
927 8 : if (has_adapted_arguments()) {
928 8 : return ArgumentsAdaptorFrame::GetLength(caller_fp());
929 : } else {
930 0 : return GetNumberOfIncomingArguments();
931 : }
932 : }
933 :
934 :
935 0 : Code* JavaScriptFrame::unchecked_code() const {
936 0 : return function()->code();
937 : }
938 :
939 :
940 5756171 : int JavaScriptFrame::GetNumberOfIncomingArguments() const {
941 : DCHECK(can_access_heap_objects() &&
942 : isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
943 :
944 11512342 : return function()->shared()->internal_formal_parameter_count();
945 : }
946 :
947 :
948 36774878 : Address JavaScriptFrame::GetCallerStackPointer() const {
949 36774878 : return fp() + StandardFrameConstants::kCallerSPOffset;
950 : }
951 :
952 46849 : void JavaScriptFrame::GetFunctions(
953 : std::vector<SharedFunctionInfo*>* functions) const {
954 : DCHECK(functions->empty());
955 140547 : functions->push_back(function()->shared());
956 46849 : }
957 :
958 52361 : void JavaScriptFrame::GetFunctions(
959 : std::vector<Handle<SharedFunctionInfo>>* functions) const {
960 : DCHECK(functions->empty());
961 : std::vector<SharedFunctionInfo*> raw_functions;
962 52361 : GetFunctions(&raw_functions);
963 157097 : for (const auto& raw_function : raw_functions) {
964 104750 : functions->push_back(Handle<SharedFunctionInfo>(raw_function));
965 : }
966 52361 : }
967 :
968 149736 : void JavaScriptFrame::Summarize(std::vector<FrameSummary>* functions) const {
969 : DCHECK(functions->empty());
970 149736 : Code* code = LookupCode();
971 149736 : int offset = static_cast<int>(pc() - code->instruction_start());
972 : AbstractCode* abstract_code = AbstractCode::cast(code);
973 149736 : FrameSummary::JavaScriptFrameSummary summary(isolate(), receiver(),
974 149736 : function(), abstract_code,
975 598944 : offset, IsConstructor());
976 149736 : functions->push_back(summary);
977 149736 : }
978 :
979 49115320 : JSFunction* JavaScriptFrame::function() const {
980 49115320 : return JSFunction::cast(function_slot_object());
981 : }
982 :
983 5507063 : Object* JavaScriptFrame::receiver() const { return GetParameter(-1); }
984 :
985 605476 : Object* JavaScriptFrame::context() const {
986 : const int offset = StandardFrameConstants::kContextOffset;
987 605476 : Object* maybe_result = Memory::Object_at(fp() + offset);
988 : DCHECK(!maybe_result->IsSmi());
989 605476 : return maybe_result;
990 : }
991 :
992 0 : Script* JavaScriptFrame::script() const {
993 0 : return Script::cast(function()->shared()->script());
994 : }
995 :
996 0 : int JavaScriptFrame::LookupExceptionHandlerInTable(
997 : int* stack_depth, HandlerTable::CatchPrediction* prediction) {
998 : DCHECK_EQ(0, LookupCode()->handler_table()->length());
999 : DCHECK(!LookupCode()->is_optimized_code());
1000 0 : return -1;
1001 : }
1002 :
1003 0 : void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function,
1004 : AbstractCode* code,
1005 : int code_offset, FILE* file,
1006 : bool print_line_number) {
1007 0 : PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
1008 0 : function->PrintName(file);
1009 0 : PrintF(file, "+%d", code_offset);
1010 0 : if (print_line_number) {
1011 : SharedFunctionInfo* shared = function->shared();
1012 0 : int source_pos = code->SourcePosition(code_offset);
1013 : Object* maybe_script = shared->script();
1014 0 : if (maybe_script->IsScript()) {
1015 : Script* script = Script::cast(maybe_script);
1016 0 : int line = script->GetLineNumber(source_pos) + 1;
1017 : Object* script_name_raw = script->name();
1018 0 : if (script_name_raw->IsString()) {
1019 : String* script_name = String::cast(script->name());
1020 : std::unique_ptr<char[]> c_script_name =
1021 0 : script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1022 0 : PrintF(file, " at %s:%d", c_script_name.get(), line);
1023 : } else {
1024 0 : PrintF(file, " at <unknown>:%d", line);
1025 : }
1026 : } else {
1027 0 : PrintF(file, " at <unknown>:<unknown>");
1028 : }
1029 : }
1030 0 : }
1031 :
1032 0 : void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
1033 : bool print_line_number) {
1034 : // constructor calls
1035 : DisallowHeapAllocation no_allocation;
1036 0 : JavaScriptFrameIterator it(isolate);
1037 0 : while (!it.done()) {
1038 0 : if (it.frame()->is_java_script()) {
1039 : JavaScriptFrame* frame = it.frame();
1040 0 : if (frame->IsConstructor()) PrintF(file, "new ");
1041 0 : JSFunction* function = frame->function();
1042 : int code_offset = 0;
1043 0 : if (frame->is_interpreted()) {
1044 : InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame);
1045 : code_offset = iframe->GetBytecodeOffset();
1046 : } else {
1047 0 : Code* code = frame->unchecked_code();
1048 0 : code_offset = static_cast<int>(frame->pc() - code->instruction_start());
1049 : }
1050 : PrintFunctionAndOffset(function, function->abstract_code(), code_offset,
1051 0 : file, print_line_number);
1052 0 : if (print_args) {
1053 : // function arguments
1054 : // (we are intentionally only printing the actually
1055 : // supplied parameters, not all parameters required)
1056 0 : PrintF(file, "(this=");
1057 0 : frame->receiver()->ShortPrint(file);
1058 0 : const int length = frame->ComputeParametersCount();
1059 0 : for (int i = 0; i < length; i++) {
1060 0 : PrintF(file, ", ");
1061 0 : frame->GetParameter(i)->ShortPrint(file);
1062 : }
1063 0 : PrintF(file, ")");
1064 : }
1065 : break;
1066 : }
1067 0 : it.Advance();
1068 : }
1069 0 : }
1070 :
1071 0 : void JavaScriptFrame::CollectFunctionAndOffsetForICStats(JSFunction* function,
1072 : AbstractCode* code,
1073 : int code_offset) {
1074 : auto ic_stats = ICStats::instance();
1075 : ICInfo& ic_info = ic_stats->Current();
1076 : SharedFunctionInfo* shared = function->shared();
1077 :
1078 0 : ic_info.function_name = ic_stats->GetOrCacheFunctionName(function);
1079 0 : ic_info.script_offset = code_offset;
1080 :
1081 0 : int source_pos = code->SourcePosition(code_offset);
1082 : Object* maybe_script = shared->script();
1083 0 : if (maybe_script->IsScript()) {
1084 : Script* script = Script::cast(maybe_script);
1085 0 : ic_info.line_num = script->GetLineNumber(source_pos) + 1;
1086 0 : ic_info.script_name = ic_stats->GetOrCacheScriptName(script);
1087 : }
1088 0 : }
1089 :
1090 0 : void JavaScriptFrame::CollectTopFrameForICStats(Isolate* isolate) {
1091 : // constructor calls
1092 : DisallowHeapAllocation no_allocation;
1093 0 : JavaScriptFrameIterator it(isolate);
1094 : ICInfo& ic_info = ICStats::instance()->Current();
1095 0 : while (!it.done()) {
1096 0 : if (it.frame()->is_java_script()) {
1097 : JavaScriptFrame* frame = it.frame();
1098 0 : if (frame->IsConstructor()) ic_info.is_constructor = true;
1099 0 : JSFunction* function = frame->function();
1100 : int code_offset = 0;
1101 0 : if (frame->is_interpreted()) {
1102 : InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame);
1103 : code_offset = iframe->GetBytecodeOffset();
1104 : } else {
1105 0 : Code* code = frame->unchecked_code();
1106 0 : code_offset = static_cast<int>(frame->pc() - code->instruction_start());
1107 : }
1108 : CollectFunctionAndOffsetForICStats(function, function->abstract_code(),
1109 0 : code_offset);
1110 0 : return;
1111 : }
1112 0 : it.Advance();
1113 : }
1114 : }
1115 :
1116 7433984 : Object* JavaScriptFrame::GetParameter(int index) const {
1117 7433984 : return Memory::Object_at(GetParameterSlot(index));
1118 : }
1119 :
1120 7538802 : int JavaScriptFrame::ComputeParametersCount() const {
1121 7538802 : return GetNumberOfIncomingArguments();
1122 : }
1123 :
1124 15 : int JavaScriptBuiltinContinuationFrame::ComputeParametersCount() const {
1125 : // Assert that the first allocatable register is also the argument count
1126 : // register.
1127 : DCHECK_EQ(RegisterConfiguration::Default()->GetAllocatableGeneralCode(0),
1128 : kJavaScriptCallArgCountRegister.code());
1129 : Object* argc_object =
1130 15 : Memory::Object_at(fp() + BuiltinContinuationFrameConstants::kArgCOffset);
1131 15 : return Smi::ToInt(argc_object);
1132 : }
1133 :
1134 : namespace {
1135 :
1136 1204924 : bool IsNonDeoptimizingAsmCode(Code* code, JSFunction* function) {
1137 2409848 : return code->is_turbofanned() && !function->shared()->HasBytecodeArray();
1138 : }
1139 :
1140 : } // namespace
1141 :
1142 7031282 : FrameSummary::JavaScriptFrameSummary::JavaScriptFrameSummary(
1143 : Isolate* isolate, Object* receiver, JSFunction* function,
1144 : AbstractCode* abstract_code, int code_offset, bool is_constructor)
1145 : : FrameSummaryBase(isolate, FrameSummary::JAVA_SCRIPT),
1146 : receiver_(receiver, isolate),
1147 : function_(function, isolate),
1148 : abstract_code_(abstract_code, isolate),
1149 : code_offset_(code_offset),
1150 7031282 : is_constructor_(is_constructor) {
1151 : DCHECK(abstract_code->IsBytecodeArray() ||
1152 : Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION ||
1153 : IsNonDeoptimizingAsmCode(Code::cast(abstract_code), function));
1154 7031282 : }
1155 :
1156 0 : bool FrameSummary::JavaScriptFrameSummary::is_subject_to_debugging() const {
1157 255044 : return function()->shared()->IsSubjectToDebugging();
1158 : }
1159 :
1160 1027970 : int FrameSummary::JavaScriptFrameSummary::SourcePosition() const {
1161 1027970 : return abstract_code()->SourcePosition(code_offset());
1162 : }
1163 :
1164 42041 : int FrameSummary::JavaScriptFrameSummary::SourceStatementPosition() const {
1165 42041 : return abstract_code()->SourceStatementPosition(code_offset());
1166 : }
1167 :
1168 1027970 : Handle<Object> FrameSummary::JavaScriptFrameSummary::script() const {
1169 2055940 : return handle(function_->shared()->script(), isolate());
1170 : }
1171 :
1172 70175 : Handle<String> FrameSummary::JavaScriptFrameSummary::FunctionName() const {
1173 263823 : return JSFunction::GetDebugName(function_);
1174 : }
1175 :
1176 10741 : Handle<Context> FrameSummary::JavaScriptFrameSummary::native_context() const {
1177 21482 : return handle(function_->context()->native_context(), isolate());
1178 : }
1179 :
1180 0 : FrameSummary::WasmFrameSummary::WasmFrameSummary(
1181 : Isolate* isolate, FrameSummary::Kind kind,
1182 : Handle<WasmInstanceObject> instance, bool at_to_number_conversion)
1183 : : FrameSummaryBase(isolate, kind),
1184 : wasm_instance_(instance),
1185 83404 : at_to_number_conversion_(at_to_number_conversion) {}
1186 :
1187 396 : Handle<Object> FrameSummary::WasmFrameSummary::receiver() const {
1188 396 : return wasm_instance_->GetIsolate()->global_proxy();
1189 : }
1190 :
1191 : #define WASM_SUMMARY_DISPATCH(type, name) \
1192 : type FrameSummary::WasmFrameSummary::name() const { \
1193 : DCHECK(kind() == Kind::WASM_COMPILED || kind() == Kind::WASM_INTERPRETED); \
1194 : return kind() == Kind::WASM_COMPILED \
1195 : ? static_cast<const WasmCompiledFrameSummary*>(this)->name() \
1196 : : static_cast<const WasmInterpretedFrameSummary*>(this) \
1197 : ->name(); \
1198 : }
1199 :
1200 41384 : WASM_SUMMARY_DISPATCH(uint32_t, function_index)
1201 41889 : WASM_SUMMARY_DISPATCH(int, byte_offset)
1202 :
1203 : #undef WASM_SUMMARY_DISPATCH
1204 :
1205 80540 : int FrameSummary::WasmFrameSummary::SourcePosition() const {
1206 : Handle<WasmCompiledModule> compiled_module(wasm_instance()->compiled_module(),
1207 40270 : isolate());
1208 : return WasmCompiledModule::GetSourcePosition(compiled_module,
1209 40270 : function_index(), byte_offset(),
1210 120810 : at_to_number_conversion());
1211 : }
1212 :
1213 40575 : Handle<Script> FrameSummary::WasmFrameSummary::script() const {
1214 40575 : return handle(wasm_instance()->compiled_module()->script());
1215 : }
1216 :
1217 396 : Handle<String> FrameSummary::WasmFrameSummary::FunctionName() const {
1218 : Handle<WasmCompiledModule> compiled_module(
1219 : wasm_instance()->compiled_module());
1220 : return WasmCompiledModule::GetFunctionName(compiled_module->GetIsolate(),
1221 396 : compiled_module, function_index());
1222 : }
1223 :
1224 0 : Handle<Context> FrameSummary::WasmFrameSummary::native_context() const {
1225 84 : return wasm_instance()->compiled_module()->native_context();
1226 : }
1227 :
1228 0 : FrameSummary::WasmCompiledFrameSummary::WasmCompiledFrameSummary(
1229 : Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> code,
1230 : int code_offset, bool at_to_number_conversion)
1231 : : WasmFrameSummary(isolate, WASM_COMPILED, instance,
1232 : at_to_number_conversion),
1233 : code_(code),
1234 0 : code_offset_(code_offset) {}
1235 :
1236 83377 : uint32_t FrameSummary::WasmCompiledFrameSummary::function_index() const {
1237 : FixedArray* deopt_data = code()->deoptimization_data();
1238 : DCHECK_EQ(2, deopt_data->length());
1239 : DCHECK(deopt_data->get(1)->IsSmi());
1240 : int val = Smi::ToInt(deopt_data->get(1));
1241 : DCHECK_LE(0, val);
1242 83377 : return static_cast<uint32_t>(val);
1243 : }
1244 :
1245 39369 : int FrameSummary::WasmCompiledFrameSummary::byte_offset() const {
1246 39369 : return AbstractCode::cast(*code())->SourcePosition(code_offset());
1247 : }
1248 :
1249 0 : FrameSummary::WasmInterpretedFrameSummary::WasmInterpretedFrameSummary(
1250 : Isolate* isolate, Handle<WasmInstanceObject> instance,
1251 : uint32_t function_index, int byte_offset)
1252 : : WasmFrameSummary(isolate, WASM_INTERPRETED, instance, false),
1253 : function_index_(function_index),
1254 0 : byte_offset_(byte_offset) {}
1255 :
1256 19950342 : FrameSummary::~FrameSummary() {
1257 : #define FRAME_SUMMARY_DESTR(kind, type, field, desc) \
1258 : case kind: \
1259 : field.~type(); \
1260 : break;
1261 19950342 : switch (base_.kind()) {
1262 : FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_DESTR)
1263 : default:
1264 0 : UNREACHABLE();
1265 : }
1266 : #undef FRAME_SUMMARY_DESTR
1267 19950342 : }
1268 :
1269 758129 : FrameSummary FrameSummary::GetTop(const StandardFrame* frame) {
1270 : std::vector<FrameSummary> frames;
1271 758129 : frames.reserve(FLAG_max_inlining_levels + 1);
1272 758129 : frame->Summarize(&frames);
1273 : DCHECK_LT(0, frames.size());
1274 758129 : return frames.back();
1275 : }
1276 :
1277 0 : FrameSummary FrameSummary::GetBottom(const StandardFrame* frame) {
1278 0 : return Get(frame, 0);
1279 : }
1280 :
1281 108 : FrameSummary FrameSummary::GetSingle(const StandardFrame* frame) {
1282 : std::vector<FrameSummary> frames;
1283 108 : frame->Summarize(&frames);
1284 : DCHECK_EQ(1, frames.size());
1285 108 : return frames.front();
1286 : }
1287 :
1288 337834 : FrameSummary FrameSummary::Get(const StandardFrame* frame, int index) {
1289 : DCHECK_LE(0, index);
1290 : std::vector<FrameSummary> frames;
1291 337834 : frames.reserve(FLAG_max_inlining_levels + 1);
1292 337834 : frame->Summarize(&frames);
1293 : DCHECK_GT(frames.size(), index);
1294 675668 : return frames[index];
1295 : }
1296 :
1297 : #define FRAME_SUMMARY_DISPATCH(ret, name) \
1298 : ret FrameSummary::name() const { \
1299 : switch (base_.kind()) { \
1300 : case JAVA_SCRIPT: \
1301 : return java_script_summary_.name(); \
1302 : case WASM_COMPILED: \
1303 : return wasm_compiled_summary_.name(); \
1304 : case WASM_INTERPRETED: \
1305 : return wasm_interpreted_summary_.name(); \
1306 : default: \
1307 : UNREACHABLE(); \
1308 : return ret{}; \
1309 : } \
1310 : }
1311 :
1312 194044 : FRAME_SUMMARY_DISPATCH(Handle<Object>, receiver)
1313 374037 : FRAME_SUMMARY_DISPATCH(int, code_offset)
1314 194044 : FRAME_SUMMARY_DISPATCH(bool, is_constructor)
1315 255799 : FRAME_SUMMARY_DISPATCH(bool, is_subject_to_debugging)
1316 1058216 : FRAME_SUMMARY_DISPATCH(Handle<Object>, script)
1317 1097555 : FRAME_SUMMARY_DISPATCH(int, SourcePosition)
1318 42041 : FRAME_SUMMARY_DISPATCH(int, SourceStatementPosition)
1319 194155 : FRAME_SUMMARY_DISPATCH(Handle<String>, FunctionName)
1320 10825 : FRAME_SUMMARY_DISPATCH(Handle<Context>, native_context)
1321 :
1322 : #undef FRAME_SUMMARY_DISPATCH
1323 :
1324 1342962 : void OptimizedFrame::Summarize(std::vector<FrameSummary>* frames) const {
1325 : DCHECK(frames->empty());
1326 : DCHECK(is_optimized());
1327 :
1328 : // Delegate to JS frame in absence of turbofan deoptimization.
1329 : // TODO(turbofan): Revisit once we support deoptimization across the board.
1330 3981069 : Code* code = LookupCode();
1331 2536203 : if (code->kind() == Code::BUILTIN ||
1332 1193241 : IsNonDeoptimizingAsmCode(code, function())) {
1333 1492683 : return JavaScriptFrame::Summarize(frames);
1334 : }
1335 :
1336 1193241 : int deopt_index = Safepoint::kNoDeoptimizationIndex;
1337 1193241 : DeoptimizationData* const data = GetDeoptimizationData(&deopt_index);
1338 1193241 : if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
1339 0 : CHECK_NULL(data);
1340 0 : FATAL("Missing deoptimization information for OptimizedFrame::Summarize.");
1341 : }
1342 :
1343 : // Prepare iteration over translation. Note that the below iteration might
1344 : // materialize objects without storing them back to the Isolate, this will
1345 : // lead to objects being re-materialized again for each summary.
1346 1193241 : TranslatedState translated(this);
1347 1193241 : translated.Prepare(fp());
1348 :
1349 : // We create the summary in reverse order because the frames
1350 : // in the deoptimization translation are ordered bottom-to-top.
1351 1193241 : bool is_constructor = IsConstructor();
1352 3924144 : for (auto it = translated.begin(); it != translated.end(); it++) {
1353 1537662 : if (it->kind() == TranslatedFrame::kInterpretedFunction ||
1354 : it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation) {
1355 : Handle<SharedFunctionInfo> shared_info = it->shared_info();
1356 :
1357 : // The translation commands are ordered and the function is always
1358 : // at the first position, and the receiver is next.
1359 : TranslatedFrame::iterator translated_values = it->begin();
1360 :
1361 : // Get or materialize the correct function in the optimized frame.
1362 : Handle<JSFunction> function =
1363 1393537 : Handle<JSFunction>::cast(translated_values->GetValue());
1364 : translated_values++;
1365 :
1366 : // Get or materialize the correct receiver in the optimized frame.
1367 1393537 : Handle<Object> receiver = translated_values->GetValue();
1368 : translated_values++;
1369 :
1370 : // Determine the underlying code object and the position within it from
1371 : // the translation corresponding to the frame type in question.
1372 : Handle<AbstractCode> abstract_code;
1373 : unsigned code_offset;
1374 1393537 : if (it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation) {
1375 : code_offset = 0;
1376 : abstract_code =
1377 : handle(AbstractCode::cast(isolate()->builtins()->builtin(
1378 754 : Builtins::GetBuiltinFromBailoutId(it->node_id()))),
1379 : isolate());
1380 : } else {
1381 : DCHECK_EQ(it->kind(), TranslatedFrame::kInterpretedFunction);
1382 1392783 : code_offset = it->node_id().ToInt(); // Points to current bytecode.
1383 : abstract_code = handle(shared_info->abstract_code(), isolate());
1384 : }
1385 :
1386 : // Append full summary of the encountered JS frame.
1387 : FrameSummary::JavaScriptFrameSummary summary(isolate(), *receiver,
1388 : *function, *abstract_code,
1389 2787074 : code_offset, is_constructor);
1390 1393537 : frames->push_back(summary);
1391 : is_constructor = false;
1392 144125 : } else if (it->kind() == TranslatedFrame::kConstructStub) {
1393 : // The next encountered JS frame will be marked as a constructor call.
1394 : DCHECK(!is_constructor);
1395 : is_constructor = true;
1396 : }
1397 : }
1398 : }
1399 :
1400 :
1401 2905719 : int OptimizedFrame::LookupExceptionHandlerInTable(
1402 : int* stack_slots, HandlerTable::CatchPrediction* prediction) {
1403 : // We cannot perform exception prediction on optimized code. Instead, we need
1404 : // to use FrameSummary to find the corresponding code offset in unoptimized
1405 : // code to perform prediction there.
1406 : DCHECK_NULL(prediction);
1407 : Code* code = LookupCode();
1408 : HandlerTable* table = HandlerTable::cast(code->handler_table());
1409 2905719 : int pc_offset = static_cast<int>(pc() - code->entry());
1410 5756727 : if (stack_slots) *stack_slots = code->stack_slots();
1411 :
1412 : // When the return pc has been replaced by a trampoline there won't be
1413 : // a handler for this trampoline. Thus we need to use the return pc that
1414 : // _used to be_ on the stack to get the right ExceptionHandler.
1415 5609910 : if (code->kind() == Code::OPTIMIZED_FUNCTION &&
1416 : code->marked_for_deoptimization()) {
1417 3144 : SafepointTable safepoints(code);
1418 3144 : pc_offset = safepoints.find_return_pc(pc_offset);
1419 : }
1420 2905719 : return table->LookupReturn(pc_offset);
1421 : }
1422 :
1423 2435573 : DeoptimizationData* OptimizedFrame::GetDeoptimizationData(
1424 : int* deopt_index) const {
1425 : DCHECK(is_optimized());
1426 :
1427 2435573 : JSFunction* opt_function = function();
1428 : Code* code = opt_function->code();
1429 :
1430 : // The code object may have been replaced by lazy deoptimization. Fall
1431 : // back to a slow search in this case to find the original optimized
1432 : // code object.
1433 2641816 : if (!code->contains(pc())) {
1434 : code = isolate()->inner_pointer_to_code_cache()->
1435 206243 : GcSafeFindCodeForInnerPointer(pc());
1436 : }
1437 : DCHECK_NOT_NULL(code);
1438 : DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
1439 :
1440 2435573 : SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1441 4871146 : *deopt_index = safepoint_entry.deoptimization_index();
1442 2435573 : if (*deopt_index != Safepoint::kNoDeoptimizationIndex) {
1443 2435573 : return DeoptimizationData::cast(code->deoptimization_data());
1444 : }
1445 : return nullptr;
1446 : }
1447 :
1448 157307 : Object* OptimizedFrame::receiver() const {
1449 149721 : Code* code = LookupCode();
1450 157307 : if (code->kind() == Code::BUILTIN) {
1451 : Address argc_ptr = fp() + OptimizedBuiltinFrameConstants::kArgCOffset;
1452 149721 : intptr_t argc = *reinterpret_cast<intptr_t*>(argc_ptr);
1453 : intptr_t args_size =
1454 149721 : (StandardFrameConstants::kFixedSlotCountAboveFp + argc) * kPointerSize;
1455 149721 : Address receiver_ptr = fp() + args_size;
1456 149721 : return *reinterpret_cast<Object**>(receiver_ptr);
1457 : } else {
1458 15172 : return JavaScriptFrame::receiver();
1459 : }
1460 : }
1461 :
1462 13723 : void OptimizedFrame::GetFunctions(
1463 : std::vector<SharedFunctionInfo*>* functions) const {
1464 : DCHECK(functions->empty());
1465 : DCHECK(is_optimized());
1466 :
1467 : // Delegate to JS frame in absence of turbofan deoptimization.
1468 : // TODO(turbofan): Revisit once we support deoptimization across the board.
1469 : Code* code = LookupCode();
1470 25406 : if (code->kind() == Code::BUILTIN ||
1471 11683 : IsNonDeoptimizingAsmCode(code, function())) {
1472 15763 : return JavaScriptFrame::GetFunctions(functions);
1473 : }
1474 :
1475 : DisallowHeapAllocation no_gc;
1476 11683 : int deopt_index = Safepoint::kNoDeoptimizationIndex;
1477 11683 : DeoptimizationData* const data = GetDeoptimizationData(&deopt_index);
1478 : DCHECK_NOT_NULL(data);
1479 : DCHECK_NE(Safepoint::kNoDeoptimizationIndex, deopt_index);
1480 : FixedArray* const literal_array = data->LiteralArray();
1481 :
1482 : TranslationIterator it(data->TranslationByteArray(),
1483 23366 : data->TranslationIndex(deopt_index)->value());
1484 11683 : Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
1485 : DCHECK_EQ(Translation::BEGIN, opcode);
1486 11683 : it.Next(); // Skip frame count.
1487 11683 : int jsframe_count = it.Next();
1488 :
1489 : // We insert the frames in reverse order because the frames
1490 : // in the deoptimization translation are ordered bottom-to-top.
1491 35406 : while (jsframe_count != 0) {
1492 12040 : opcode = static_cast<Translation::Opcode>(it.Next());
1493 24080 : if (opcode == Translation::INTERPRETED_FRAME ||
1494 12040 : opcode == Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME) {
1495 11739 : it.Next(); // Skip bailout id.
1496 11739 : jsframe_count--;
1497 :
1498 : // The second operand of the frame points to the function.
1499 11739 : Object* shared = literal_array->get(it.Next());
1500 23478 : functions->push_back(SharedFunctionInfo::cast(shared));
1501 :
1502 : // Skip over remaining operands to advance to the next opcode.
1503 11739 : it.Skip(Translation::NumberOfOperandsFor(opcode) - 2);
1504 : } else {
1505 : // Skip over operands to advance to the next opcode.
1506 301 : it.Skip(Translation::NumberOfOperandsFor(opcode));
1507 : }
1508 : }
1509 : }
1510 :
1511 :
1512 7896660 : int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) {
1513 7896660 : return StandardFrameConstants::kCallerSPOffset -
1514 7896660 : ((slot_index + 1) * kPointerSize);
1515 : }
1516 :
1517 :
1518 0 : Object* OptimizedFrame::StackSlotAt(int index) const {
1519 0 : return Memory::Object_at(fp() + StackSlotOffsetRelativeToFp(index));
1520 : }
1521 :
1522 0 : int InterpretedFrame::position() const {
1523 : AbstractCode* code = AbstractCode::cast(GetBytecodeArray());
1524 : int code_offset = GetBytecodeOffset();
1525 0 : return code->SourcePosition(code_offset);
1526 : }
1527 :
1528 14512063 : int InterpretedFrame::LookupExceptionHandlerInTable(
1529 : int* context_register, HandlerTable::CatchPrediction* prediction) {
1530 14512063 : BytecodeArray* bytecode = function()->shared()->bytecode_array();
1531 : HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
1532 14512063 : return table->LookupRange(GetBytecodeOffset(), context_register, prediction);
1533 : }
1534 :
1535 64370 : int InterpretedFrame::GetBytecodeOffset() const {
1536 : const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1537 : DCHECK_EQ(
1538 : InterpreterFrameConstants::kBytecodeOffsetFromFp,
1539 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1540 20064442 : int raw_offset = Smi::ToInt(GetExpression(index));
1541 20064451 : return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
1542 : }
1543 :
1544 0 : int InterpretedFrame::GetBytecodeOffset(Address fp) {
1545 : const int offset = InterpreterFrameConstants::kExpressionsOffset;
1546 : const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1547 : DCHECK_EQ(
1548 : InterpreterFrameConstants::kBytecodeOffsetFromFp,
1549 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1550 : Address expression_offset = fp + offset - index * kPointerSize;
1551 0 : int raw_offset = Smi::ToInt(Memory::Object_at(expression_offset));
1552 0 : return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
1553 : }
1554 :
1555 791862 : void InterpretedFrame::PatchBytecodeOffset(int new_offset) {
1556 : const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1557 : DCHECK_EQ(
1558 : InterpreterFrameConstants::kBytecodeOffsetFromFp,
1559 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1560 791862 : int raw_offset = new_offset + BytecodeArray::kHeaderSize - kHeapObjectTag;
1561 791862 : SetExpression(index, Smi::FromInt(raw_offset));
1562 791862 : }
1563 :
1564 14253883 : BytecodeArray* InterpretedFrame::GetBytecodeArray() const {
1565 : const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1566 : DCHECK_EQ(
1567 : InterpreterFrameConstants::kBytecodeArrayFromFp,
1568 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1569 28507775 : return BytecodeArray::cast(GetExpression(index));
1570 : }
1571 :
1572 8452 : void InterpretedFrame::PatchBytecodeArray(BytecodeArray* bytecode_array) {
1573 : const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1574 : DCHECK_EQ(
1575 : InterpreterFrameConstants::kBytecodeArrayFromFp,
1576 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1577 8452 : SetExpression(index, bytecode_array);
1578 8452 : }
1579 :
1580 791862 : Object* InterpretedFrame::ReadInterpreterRegister(int register_index) const {
1581 : const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1582 : DCHECK_EQ(
1583 : InterpreterFrameConstants::kRegisterFileFromFp,
1584 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1585 1583724 : return GetExpression(index + register_index);
1586 : }
1587 :
1588 0 : void InterpretedFrame::WriteInterpreterRegister(int register_index,
1589 : Object* value) {
1590 : const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1591 : DCHECK_EQ(
1592 : InterpreterFrameConstants::kRegisterFileFromFp,
1593 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1594 0 : return SetExpression(index + register_index, value);
1595 : }
1596 :
1597 5488009 : void InterpretedFrame::Summarize(std::vector<FrameSummary>* functions) const {
1598 : DCHECK(functions->empty());
1599 : AbstractCode* abstract_code =
1600 5488009 : AbstractCode::cast(function()->shared()->bytecode_array());
1601 : FrameSummary::JavaScriptFrameSummary summary(
1602 10976018 : isolate(), receiver(), function(), abstract_code, GetBytecodeOffset(),
1603 16464027 : IsConstructor());
1604 5488009 : functions->push_back(summary);
1605 5488009 : }
1606 :
1607 1782631 : int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
1608 3565262 : return Smi::ToInt(GetExpression(0));
1609 : }
1610 :
1611 0 : int ArgumentsAdaptorFrame::GetLength(Address fp) {
1612 : const int offset = ArgumentsAdaptorFrameConstants::kLengthOffset;
1613 8 : return Smi::ToInt(Memory::Object_at(fp + offset));
1614 : }
1615 :
1616 0 : Code* ArgumentsAdaptorFrame::unchecked_code() const {
1617 : return isolate()->builtins()->builtin(
1618 0 : Builtins::kArgumentsAdaptorTrampoline);
1619 : }
1620 :
1621 0 : int BuiltinFrame::GetNumberOfIncomingArguments() const {
1622 0 : return Smi::ToInt(GetExpression(0));
1623 : }
1624 :
1625 0 : void BuiltinFrame::PrintFrameKind(StringStream* accumulator) const {
1626 0 : accumulator->Add("builtin frame: ");
1627 0 : }
1628 :
1629 2260611 : Address InternalFrame::GetCallerStackPointer() const {
1630 : // Internal frames have no arguments. The stack pointer of the
1631 : // caller is at a fixed offset from the frame pointer.
1632 2260611 : return fp() + StandardFrameConstants::kCallerSPOffset;
1633 : }
1634 :
1635 0 : Code* InternalFrame::unchecked_code() const {
1636 : const int offset = InternalFrameConstants::kCodeOffset;
1637 0 : Object* code = Memory::Object_at(fp() + offset);
1638 : DCHECK_NOT_NULL(code);
1639 0 : return reinterpret_cast<Code*>(code);
1640 : }
1641 :
1642 :
1643 0 : void WasmCompiledFrame::Print(StringStream* accumulator, PrintMode mode,
1644 : int index) const {
1645 : PrintIndex(accumulator, mode, index);
1646 0 : accumulator->Add("WASM [");
1647 0 : Script* script = this->script();
1648 0 : accumulator->PrintName(script->name());
1649 0 : int pc = static_cast<int>(this->pc() - LookupCode()->instruction_start());
1650 0 : Object* instance = this->wasm_instance();
1651 : Vector<const uint8_t> raw_func_name =
1652 : WasmInstanceObject::cast(instance)->compiled_module()->GetRawFunctionName(
1653 0 : this->function_index());
1654 0 : const int kMaxPrintedFunctionName = 64;
1655 : char func_name[kMaxPrintedFunctionName + 1];
1656 0 : int func_name_len = std::min(kMaxPrintedFunctionName, raw_func_name.length());
1657 0 : memcpy(func_name, raw_func_name.start(), func_name_len);
1658 0 : func_name[func_name_len] = '\0';
1659 : accumulator->Add("], function #%u ('%s'), pc=%p, pos=%d\n",
1660 0 : this->function_index(), func_name, pc, this->position());
1661 0 : if (mode != OVERVIEW) accumulator->Add("\n");
1662 0 : }
1663 :
1664 0 : Code* WasmCompiledFrame::unchecked_code() const {
1665 0 : return isolate()->FindCodeObject(pc());
1666 : }
1667 :
1668 6454 : void WasmCompiledFrame::Iterate(RootVisitor* v) const {
1669 6454 : IterateCompiledFrame(v);
1670 6454 : }
1671 :
1672 2857659 : Address WasmCompiledFrame::GetCallerStackPointer() const {
1673 2857659 : return fp() + ExitFrameConstants::kCallerSPOffset;
1674 : }
1675 :
1676 83512 : WasmInstanceObject* WasmCompiledFrame::wasm_instance() const {
1677 83512 : WasmInstanceObject* obj = WasmInstanceObject::GetOwningInstance(LookupCode());
1678 : // This is a live stack frame; it must have a live instance.
1679 : DCHECK_NOT_NULL(obj);
1680 83512 : return obj;
1681 : }
1682 :
1683 54 : uint32_t WasmCompiledFrame::function_index() const {
1684 54 : return FrameSummary::GetSingle(this).AsWasmCompiled().function_index();
1685 : }
1686 :
1687 0 : Script* WasmCompiledFrame::script() const {
1688 0 : return wasm_instance()->compiled_module()->script();
1689 : }
1690 :
1691 54 : int WasmCompiledFrame::position() const {
1692 54 : return FrameSummary::GetSingle(this).SourcePosition();
1693 : }
1694 :
1695 83404 : void WasmCompiledFrame::Summarize(std::vector<FrameSummary>* functions) const {
1696 : DCHECK(functions->empty());
1697 250212 : Handle<Code> code(LookupCode(), isolate());
1698 166808 : int offset = static_cast<int>(pc() - code->instruction_start());
1699 83404 : Handle<WasmInstanceObject> instance(wasm_instance(), isolate());
1700 : FrameSummary::WasmCompiledFrameSummary summary(
1701 83404 : isolate(), instance, code, offset, at_to_number_conversion());
1702 83404 : functions->push_back(summary);
1703 83404 : }
1704 :
1705 83894 : bool WasmCompiledFrame::at_to_number_conversion() const {
1706 : // Check whether our callee is a WASM_TO_JS frame, and this frame is at the
1707 : // ToNumber conversion call.
1708 89496 : Address callee_pc = reinterpret_cast<Address>(this->callee_pc());
1709 89496 : Code* code = callee_pc ? isolate()->FindCodeObject(callee_pc) : nullptr;
1710 89496 : if (!code || code->kind() != Code::WASM_TO_JS_FUNCTION) return false;
1711 626 : int offset = static_cast<int>(callee_pc - code->instruction_start());
1712 626 : int pos = AbstractCode::cast(code)->SourcePosition(offset);
1713 : DCHECK(pos == 0 || pos == 1);
1714 : // The imported call has position 0, ToNumber has position 1.
1715 626 : return !!pos;
1716 : }
1717 :
1718 280 : int WasmCompiledFrame::LookupExceptionHandlerInTable(int* stack_slots) {
1719 : DCHECK_NOT_NULL(stack_slots);
1720 : Code* code = LookupCode();
1721 : HandlerTable* table = HandlerTable::cast(code->handler_table());
1722 280 : int pc_offset = static_cast<int>(pc() - code->entry());
1723 280 : *stack_slots = code->stack_slots();
1724 280 : return table->LookupReturn(pc_offset);
1725 : }
1726 :
1727 3 : void WasmInterpreterEntryFrame::Iterate(RootVisitor* v) const {
1728 3 : IterateCompiledFrame(v);
1729 3 : }
1730 :
1731 0 : void WasmInterpreterEntryFrame::Print(StringStream* accumulator, PrintMode mode,
1732 : int index) const {
1733 : PrintIndex(accumulator, mode, index);
1734 0 : accumulator->Add("WASM INTERPRETER ENTRY [");
1735 0 : Script* script = this->script();
1736 0 : accumulator->PrintName(script->name());
1737 0 : accumulator->Add("]");
1738 0 : if (mode != OVERVIEW) accumulator->Add("\n");
1739 0 : }
1740 :
1741 2879 : void WasmInterpreterEntryFrame::Summarize(
1742 : std::vector<FrameSummary>* functions) const {
1743 1320203 : Handle<WasmInstanceObject> instance(wasm_instance(), isolate());
1744 : std::vector<std::pair<uint32_t, int>> interpreted_stack =
1745 2879 : instance->debug_info()->GetInterpretedStack(fp());
1746 :
1747 1320203 : for (auto& e : interpreted_stack) {
1748 : FrameSummary::WasmInterpretedFrameSummary summary(isolate(), instance,
1749 1314445 : e.first, e.second);
1750 1314445 : functions->push_back(summary);
1751 : }
1752 2879 : }
1753 :
1754 0 : Code* WasmInterpreterEntryFrame::unchecked_code() const {
1755 0 : return isolate()->FindCodeObject(pc());
1756 : }
1757 :
1758 4559 : WasmInstanceObject* WasmInterpreterEntryFrame::wasm_instance() const {
1759 4559 : WasmInstanceObject* ret = WasmInstanceObject::GetOwningInstance(LookupCode());
1760 : // This is a live stack frame, there must be a live wasm instance available.
1761 : DCHECK_NOT_NULL(ret);
1762 4559 : return ret;
1763 : }
1764 :
1765 0 : Script* WasmInterpreterEntryFrame::script() const {
1766 0 : return wasm_instance()->compiled_module()->script();
1767 : }
1768 :
1769 0 : int WasmInterpreterEntryFrame::position() const {
1770 0 : return FrameSummary::GetBottom(this).AsWasmInterpreted().SourcePosition();
1771 : }
1772 :
1773 285 : Object* WasmInterpreterEntryFrame::context() const {
1774 570 : return wasm_instance()->compiled_module()->ptr_to_native_context();
1775 : }
1776 :
1777 3068 : Address WasmInterpreterEntryFrame::GetCallerStackPointer() const {
1778 3068 : return fp() + ExitFrameConstants::kCallerSPOffset;
1779 : }
1780 :
1781 : namespace {
1782 :
1783 :
1784 0 : void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared,
1785 : Code* code) {
1786 0 : if (FLAG_max_stack_trace_source_length != 0 && code != nullptr) {
1787 0 : std::ostringstream os;
1788 0 : os << "--------- s o u r c e c o d e ---------\n"
1789 0 : << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1790 0 : << "\n-----------------------------------------\n";
1791 0 : accumulator->Add(os.str().c_str());
1792 : }
1793 0 : }
1794 :
1795 :
1796 : } // namespace
1797 :
1798 :
1799 10 : void JavaScriptFrame::Print(StringStream* accumulator,
1800 : PrintMode mode,
1801 : int index) const {
1802 : DisallowHeapAllocation no_gc;
1803 10 : Object* receiver = this->receiver();
1804 10 : JSFunction* function = this->function();
1805 :
1806 10 : accumulator->PrintSecurityTokenIfChanged(function);
1807 : PrintIndex(accumulator, mode, index);
1808 10 : PrintFrameKind(accumulator);
1809 10 : Code* code = nullptr;
1810 10 : if (IsConstructor()) accumulator->Add("new ");
1811 10 : accumulator->PrintFunction(function, receiver, &code);
1812 :
1813 : // Get scope information for nicer output, if possible. If code is nullptr, or
1814 : // doesn't contain scope info, scope_info will return 0 for the number of
1815 : // parameters, stack local variables, context local variables, stack slots,
1816 : // or context slots.
1817 : SharedFunctionInfo* shared = function->shared();
1818 : ScopeInfo* scope_info = shared->scope_info();
1819 : Object* script_obj = shared->script();
1820 10 : if (script_obj->IsScript()) {
1821 : Script* script = Script::cast(script_obj);
1822 10 : accumulator->Add(" [");
1823 10 : accumulator->PrintName(script->name());
1824 :
1825 : Address pc = this->pc();
1826 20 : if (is_interpreted()) {
1827 : const InterpretedFrame* iframe =
1828 : reinterpret_cast<const InterpretedFrame*>(this);
1829 : BytecodeArray* bytecodes = iframe->GetBytecodeArray();
1830 : int offset = iframe->GetBytecodeOffset();
1831 9 : int source_pos = AbstractCode::cast(bytecodes)->SourcePosition(offset);
1832 9 : int line = script->GetLineNumber(source_pos) + 1;
1833 9 : accumulator->Add(":%d] [bytecode=%p offset=%d]", line, bytecodes, offset);
1834 : } else {
1835 : int function_start_pos = shared->start_position();
1836 1 : int line = script->GetLineNumber(function_start_pos) + 1;
1837 1 : accumulator->Add(":~%d] [pc=%p]", line, pc);
1838 : }
1839 : }
1840 :
1841 10 : accumulator->Add("(this=%o", receiver);
1842 :
1843 : // Print the parameters.
1844 10 : int parameters_count = ComputeParametersCount();
1845 10 : for (int i = 0; i < parameters_count; i++) {
1846 0 : accumulator->Add(",");
1847 : // If we have a name for the parameter we print it. Nameless
1848 : // parameters are either because we have more actual parameters
1849 : // than formal parameters or because we have no scope information.
1850 0 : if (i < scope_info->ParameterCount()) {
1851 0 : accumulator->PrintName(scope_info->ParameterName(i));
1852 0 : accumulator->Add("=");
1853 : }
1854 0 : accumulator->Add("%o", GetParameter(i));
1855 : }
1856 :
1857 10 : accumulator->Add(")");
1858 10 : if (mode == OVERVIEW) {
1859 10 : accumulator->Add("\n");
1860 10 : return;
1861 : }
1862 0 : if (is_optimized()) {
1863 0 : accumulator->Add(" {\n// optimized frame\n");
1864 0 : PrintFunctionSource(accumulator, shared, code);
1865 0 : accumulator->Add("}\n");
1866 0 : return;
1867 : }
1868 0 : accumulator->Add(" {\n");
1869 :
1870 : // Compute the number of locals and expression stack elements.
1871 0 : int stack_locals_count = scope_info->StackLocalCount();
1872 0 : int heap_locals_count = scope_info->ContextLocalCount();
1873 0 : int expressions_count = ComputeExpressionsCount();
1874 :
1875 : // Print stack-allocated local variables.
1876 0 : if (stack_locals_count > 0) {
1877 0 : accumulator->Add(" // stack-allocated locals\n");
1878 : }
1879 0 : for (int i = 0; i < stack_locals_count; i++) {
1880 0 : accumulator->Add(" var ");
1881 0 : accumulator->PrintName(scope_info->StackLocalName(i));
1882 0 : accumulator->Add(" = ");
1883 0 : if (i < expressions_count) {
1884 0 : accumulator->Add("%o", GetExpression(i));
1885 : } else {
1886 0 : accumulator->Add("// no expression found - inconsistent frame?");
1887 : }
1888 0 : accumulator->Add("\n");
1889 : }
1890 :
1891 : // Try to get hold of the context of this frame.
1892 : Context* context = nullptr;
1893 0 : if (this->context() != nullptr && this->context()->IsContext()) {
1894 0 : context = Context::cast(this->context());
1895 : }
1896 0 : while (context->IsWithContext()) {
1897 : context = context->previous();
1898 : DCHECK_NOT_NULL(context);
1899 : }
1900 :
1901 : // Print heap-allocated local variables.
1902 0 : if (heap_locals_count > 0) {
1903 0 : accumulator->Add(" // heap-allocated locals\n");
1904 : }
1905 0 : for (int i = 0; i < heap_locals_count; i++) {
1906 0 : accumulator->Add(" var ");
1907 0 : accumulator->PrintName(scope_info->ContextLocalName(i));
1908 0 : accumulator->Add(" = ");
1909 0 : if (context != nullptr) {
1910 0 : int index = Context::MIN_CONTEXT_SLOTS + i;
1911 0 : if (index < context->length()) {
1912 0 : accumulator->Add("%o", context->get(index));
1913 : } else {
1914 : accumulator->Add(
1915 0 : "// warning: missing context slot - inconsistent frame?");
1916 : }
1917 : } else {
1918 0 : accumulator->Add("// warning: no context found - inconsistent frame?");
1919 : }
1920 0 : accumulator->Add("\n");
1921 : }
1922 :
1923 : // Print the expression stack.
1924 : int expressions_start = stack_locals_count;
1925 0 : if (expressions_start < expressions_count) {
1926 0 : accumulator->Add(" // expression stack (top to bottom)\n");
1927 : }
1928 0 : for (int i = expressions_count - 1; i >= expressions_start; i--) {
1929 0 : accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1930 : }
1931 :
1932 0 : PrintFunctionSource(accumulator, shared, code);
1933 :
1934 0 : accumulator->Add("}\n\n");
1935 : }
1936 :
1937 :
1938 0 : void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1939 : PrintMode mode,
1940 : int index) const {
1941 0 : int actual = ComputeParametersCount();
1942 : int expected = -1;
1943 0 : JSFunction* function = this->function();
1944 : expected = function->shared()->internal_formal_parameter_count();
1945 :
1946 : PrintIndex(accumulator, mode, index);
1947 0 : accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1948 0 : if (mode == OVERVIEW) {
1949 0 : accumulator->Add("\n");
1950 0 : return;
1951 : }
1952 0 : accumulator->Add(" {\n");
1953 :
1954 : // Print actual arguments.
1955 0 : if (actual > 0) accumulator->Add(" // actual arguments\n");
1956 0 : for (int i = 0; i < actual; i++) {
1957 0 : accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1958 0 : if (expected != -1 && i >= expected) {
1959 0 : accumulator->Add(" // not passed to callee");
1960 : }
1961 0 : accumulator->Add("\n");
1962 : }
1963 :
1964 0 : accumulator->Add("}\n\n");
1965 : }
1966 :
1967 119488 : void EntryFrame::Iterate(RootVisitor* v) const {
1968 119488 : IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
1969 119488 : }
1970 :
1971 0 : void StandardFrame::IterateExpressions(RootVisitor* v) const {
1972 : const int offset = StandardFrameConstants::kLastObjectOffset;
1973 2019733 : Object** base = &Memory::Object_at(sp());
1974 : Object** limit = &Memory::Object_at(fp() + offset) + 1;
1975 2019733 : v->VisitRootPointers(Root::kTop, base, limit);
1976 0 : }
1977 :
1978 1884407 : void JavaScriptFrame::Iterate(RootVisitor* v) const {
1979 : IterateExpressions(v);
1980 1884407 : IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
1981 1884407 : }
1982 :
1983 135326 : void InternalFrame::Iterate(RootVisitor* v) const {
1984 135326 : Code* code = LookupCode();
1985 : IteratePc(v, pc_address(), constant_pool_address(), code);
1986 : // Internal frames typically do not receive any arguments, hence their stack
1987 : // only contains tagged pointers.
1988 : // We are misusing the has_tagged_params flag here to tell us whether
1989 : // the full stack frame contains only tagged pointers or only raw values.
1990 : // This is used for the WasmCompileLazy builtin, where we actually pass
1991 : // untagged arguments and also store untagged values on the stack.
1992 135326 : if (code->has_tagged_params()) IterateExpressions(v);
1993 135326 : }
1994 :
1995 : // -------------------------------------------------------------------------
1996 :
1997 8947472 : static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1998 : MapWord map_word = object->map_word();
1999 : return map_word.IsForwardingAddress() ?
2000 17894944 : map_word.ToForwardingAddress()->map() : map_word.ToMap();
2001 : }
2002 :
2003 :
2004 8947472 : static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
2005 8947472 : return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
2006 : }
2007 :
2008 :
2009 : #ifdef DEBUG
2010 : static bool GcSafeCodeContains(HeapObject* code, Address addr) {
2011 : Map* map = GcSafeMapOfCodeSpaceObject(code);
2012 : DCHECK(map == code->GetHeap()->code_map());
2013 : Address start = code->address();
2014 : Address end = code->address() + code->SizeFromMap(map);
2015 : return start <= addr && addr < end;
2016 : }
2017 : #endif
2018 :
2019 :
2020 0 : Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
2021 : Address inner_pointer) {
2022 : Code* code = reinterpret_cast<Code*>(object);
2023 : DCHECK(code != nullptr && GcSafeCodeContains(code, inner_pointer));
2024 0 : return code;
2025 : }
2026 :
2027 :
2028 1472176 : Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
2029 : Address inner_pointer) {
2030 5888701 : Heap* heap = isolate_->heap();
2031 :
2032 : // Check if the inner pointer points into a large object chunk.
2033 1472176 : LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
2034 1472176 : if (large_page != nullptr) {
2035 1 : return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
2036 : }
2037 :
2038 1472175 : if (!heap->code_space()->Contains(inner_pointer)) {
2039 : return nullptr;
2040 : }
2041 :
2042 : // Iterate through the page until we reach the end or find an object starting
2043 : // after the inner pointer.
2044 : Page* page = Page::FromAddress(inner_pointer);
2045 :
2046 : DCHECK_EQ(page->owner(), heap->code_space());
2047 1472175 : heap->mark_compact_collector()->sweeper().SweepOrWaitUntilSweepingCompleted(
2048 1472175 : page);
2049 :
2050 1472175 : Address addr = page->skip_list()->StartFor(inner_pointer);
2051 :
2052 : Address top = heap->code_space()->top();
2053 : Address limit = heap->code_space()->limit();
2054 :
2055 : while (true) {
2056 8947587 : if (addr == top && addr != limit) {
2057 : addr = limit;
2058 : continue;
2059 : }
2060 :
2061 8947472 : HeapObject* obj = HeapObject::FromAddress(addr);
2062 8947472 : int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
2063 8947472 : Address next_addr = addr + obj_size;
2064 8947472 : if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
2065 : addr = next_addr;
2066 : }
2067 : }
2068 :
2069 :
2070 : InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
2071 63929825 : InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
2072 127859650 : isolate_->counters()->pc_to_code()->Increment();
2073 : DCHECK(base::bits::IsPowerOfTwo(kInnerPointerToCodeCacheSize));
2074 : uint32_t hash = ComputeIntegerHash(ObjectAddressForHashing(inner_pointer));
2075 63929829 : uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
2076 63929829 : InnerPointerToCodeCacheEntry* entry = cache(index);
2077 63929829 : if (entry->inner_pointer == inner_pointer) {
2078 125379188 : isolate_->counters()->pc_to_code_cached()->Increment();
2079 : DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
2080 : } else {
2081 : // Because this code may be interrupted by a profiling signal that
2082 : // also queries the cache, we cannot update inner_pointer before the code
2083 : // has been set. Otherwise, we risk trying to use a cache entry before
2084 : // the code has been computed.
2085 1240235 : entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
2086 : entry->safepoint_entry.Reset();
2087 1240235 : entry->inner_pointer = inner_pointer;
2088 : }
2089 63929828 : return entry;
2090 : }
2091 :
2092 :
2093 : // -------------------------------------------------------------------------
2094 :
2095 :
2096 : #define DEFINE_WRAPPER(type, field) \
2097 : class field##_Wrapper : public ZoneObject { \
2098 : public: /* NOLINT */ \
2099 : field##_Wrapper(const field& original) : frame_(original) { \
2100 : } \
2101 : field frame_; \
2102 : };
2103 : STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
2104 : #undef DEFINE_WRAPPER
2105 :
2106 13512 : static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
2107 : #define FRAME_TYPE_CASE(type, field) \
2108 : case StackFrame::type: { \
2109 : field##_Wrapper* wrapper = \
2110 : new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
2111 : return &wrapper->frame_; \
2112 : }
2113 :
2114 13512 : switch (frame->type()) {
2115 13512 : STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
2116 0 : default: UNREACHABLE();
2117 : }
2118 : #undef FRAME_TYPE_CASE
2119 : return nullptr;
2120 : }
2121 :
2122 :
2123 622 : Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
2124 622 : ZoneList<StackFrame*> list(10, zone);
2125 14134 : for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
2126 13512 : StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
2127 13512 : list.Add(frame, zone);
2128 : }
2129 1244 : return list.ToVector();
2130 : }
2131 :
2132 :
2133 : } // namespace internal
2134 : } // namespace v8
|