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/macro-assembler.h"
15 : #include "src/objects/code.h"
16 : #include "src/objects/slots.h"
17 : #include "src/objects/smi.h"
18 : #include "src/register-configuration.h"
19 : #include "src/safepoint-table.h"
20 : #include "src/snapshot/snapshot.h"
21 : #include "src/string-stream.h"
22 : #include "src/visitors.h"
23 : #include "src/vm-state-inl.h"
24 : #include "src/wasm/wasm-code-manager.h"
25 : #include "src/wasm/wasm-engine.h"
26 : #include "src/wasm/wasm-objects-inl.h"
27 : #include "src/zone/zone-containers.h"
28 :
29 : namespace v8 {
30 : namespace internal {
31 :
32 : ReturnAddressLocationResolver StackFrame::return_address_location_resolver_ =
33 : nullptr;
34 :
35 : // Iterator that supports traversing the stack handlers of a
36 : // particular frame. Needs to know the top of the handler chain.
37 : class StackHandlerIterator {
38 : public:
39 : StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
40 : : limit_(frame->fp()), handler_(handler) {
41 : // Make sure the handler has already been unwound to this frame.
42 : DCHECK(frame->sp() <= handler->address());
43 : }
44 :
45 : StackHandler* handler() const { return handler_; }
46 :
47 102177800 : bool done() { return handler_ == nullptr || handler_->address() > limit_; }
48 : void Advance() {
49 : DCHECK(!done());
50 : handler_ = handler_->next();
51 : }
52 :
53 : private:
54 : const Address limit_;
55 : StackHandler* handler_;
56 : };
57 :
58 :
59 : // -------------------------------------------------------------------------
60 :
61 :
62 : #define INITIALIZE_SINGLETON(type, field) field##_(this),
63 9071853 : StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
64 : bool can_access_heap_objects)
65 : : isolate_(isolate),
66 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON) frame_(nullptr),
67 : handler_(nullptr),
68 18143706 : can_access_heap_objects_(can_access_heap_objects) {}
69 : #undef INITIALIZE_SINGLETON
70 :
71 6491992 : StackFrameIterator::StackFrameIterator(Isolate* isolate)
72 6492011 : : StackFrameIterator(isolate, isolate->thread_local_top()) {}
73 :
74 559870 : StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
75 9008037 : : StackFrameIteratorBase(isolate, true) {
76 9008087 : Reset(t);
77 559870 : }
78 :
79 50157490 : void StackFrameIterator::Advance() {
80 : DCHECK(!done());
81 : // Compute the state of the calling frame before restoring
82 : // callee-saved registers and unwinding handlers. This allows the
83 : // frame code that computes the caller state to access the top
84 : // handler and the value of any callee-saved register if needed.
85 50157490 : StackFrame::State state;
86 50157490 : StackFrame::Type type = frame_->GetCallerState(&state);
87 :
88 : // Unwind handlers corresponding to the current frame.
89 50157642 : StackHandlerIterator it(frame_, handler_);
90 51759238 : while (!it.done()) it.Advance();
91 50157642 : handler_ = it.handler();
92 :
93 : // Advance to the calling frame.
94 50157642 : frame_ = SingletonFor(type, &state);
95 :
96 : // When we're done iterating over the stack frames, the handler
97 : // chain must have been completely unwound.
98 : DCHECK(!done() || handler_ == nullptr);
99 50157615 : }
100 :
101 :
102 9008067 : void StackFrameIterator::Reset(ThreadLocalTop* top) {
103 9008067 : StackFrame::State state;
104 : StackFrame::Type type = ExitFrame::GetStateForFramePointer(
105 9008067 : Isolate::c_entry_fp(top), &state);
106 9008058 : handler_ = StackHandler::FromAddress(Isolate::handler(top));
107 9008058 : frame_ = SingletonFor(type, &state);
108 9008057 : }
109 :
110 :
111 59542647 : StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
112 : StackFrame::State* state) {
113 59542647 : StackFrame* result = SingletonFor(type);
114 : DCHECK((!result) == (type == StackFrame::NONE));
115 59542606 : if (result) result->state_ = *state;
116 59542606 : return result;
117 : }
118 :
119 :
120 59855998 : StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
121 : #define FRAME_TYPE_CASE(type, field) \
122 : case StackFrame::type: \
123 : return &field##_;
124 :
125 59855998 : switch (type) {
126 : case StackFrame::NONE:
127 : return nullptr;
128 1848288 : STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
129 : default: break;
130 : }
131 : return nullptr;
132 :
133 : #undef FRAME_TYPE_CASE
134 : }
135 :
136 : // -------------------------------------------------------------------------
137 :
138 1323544 : void JavaScriptFrameIterator::Advance() {
139 2647937 : do {
140 2647937 : iterator_.Advance();
141 2647937 : } while (!iterator_.done() && !iterator_.frame()->is_java_script());
142 1323544 : }
143 :
144 : // -------------------------------------------------------------------------
145 :
146 1956175 : StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
147 1956175 : : iterator_(isolate) {
148 1956175 : if (!done() && !IsValidFrame(iterator_.frame())) Advance();
149 1956175 : }
150 :
151 185522 : StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate,
152 : StackFrame::Id id)
153 185522 : : StackTraceFrameIterator(isolate) {
154 2396512 : while (!done() && frame()->id() != id) Advance();
155 185522 : }
156 :
157 3769825 : void StackTraceFrameIterator::Advance() {
158 6699850 : do {
159 6699850 : iterator_.Advance();
160 6699850 : } while (!done() && !IsValidFrame(iterator_.frame()));
161 3769825 : }
162 :
163 8453409 : bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
164 8453409 : if (frame->is_java_script()) {
165 : JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame);
166 7852484 : if (!jsFrame->function()->IsJSFunction()) return false;
167 7852484 : return jsFrame->function()->shared()->IsSubjectToDebugging();
168 : }
169 : // apart from javascript, only wasm is valid
170 4527167 : return frame->is_wasm();
171 : }
172 :
173 : // -------------------------------------------------------------------------
174 :
175 : namespace {
176 :
177 403334 : bool IsInterpreterFramePc(Isolate* isolate, Address pc,
178 : StackFrame::State* state) {
179 : Code interpreter_entry_trampoline =
180 403334 : isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
181 : Code interpreter_bytecode_advance =
182 403334 : isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeAdvance);
183 : Code interpreter_bytecode_dispatch =
184 403334 : isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
185 :
186 864202 : if (interpreter_entry_trampoline->contains(pc) ||
187 460868 : interpreter_bytecode_advance->contains(pc) ||
188 57534 : interpreter_bytecode_dispatch->contains(pc)) {
189 : return true;
190 57534 : } else if (FLAG_interpreted_frames_native_stack) {
191 : intptr_t marker = Memory<intptr_t>(
192 0 : state->fp + CommonFrameConstants::kContextOrFrameTypeOffset);
193 : MSAN_MEMORY_IS_INITIALIZED(
194 : state->fp + StandardFrameConstants::kFunctionOffset,
195 : kSystemPointerSize);
196 : Object maybe_function = Object(
197 0 : Memory<Address>(state->fp + StandardFrameConstants::kFunctionOffset));
198 : // There's no need to run a full ContainsSlow if we know the frame can't be
199 : // an InterpretedFrame, so we do these fast checks first
200 0 : if (StackFrame::IsTypeMarker(marker) || maybe_function->IsSmi()) {
201 : return false;
202 0 : } else if (!isolate->heap()->InSpaceSlow(pc, CODE_SPACE)) {
203 : return false;
204 : }
205 : interpreter_entry_trampoline =
206 0 : isolate->heap()->GcSafeFindCodeForInnerPointer(pc);
207 : return interpreter_entry_trampoline->is_interpreter_trampoline_builtin();
208 : } else {
209 : return false;
210 : }
211 : }
212 :
213 : DISABLE_ASAN Address ReadMemoryAt(Address address) {
214 43601 : return Memory<Address>(address);
215 : }
216 :
217 : } // namespace
218 :
219 63811 : SafeStackFrameIterator::SafeStackFrameIterator(
220 : Isolate* isolate,
221 : Address fp, Address sp, Address js_entry_sp)
222 : : StackFrameIteratorBase(isolate, false),
223 : low_bound_(sp),
224 : high_bound_(js_entry_sp),
225 : top_frame_type_(StackFrame::NONE),
226 127622 : external_callback_scope_(isolate->external_callback_scope()) {
227 63811 : StackFrame::State state;
228 : StackFrame::Type type;
229 : ThreadLocalTop* top = isolate->thread_local_top();
230 : bool advance_frame = true;
231 :
232 : Address fast_c_fp = isolate->isolate_data()->fast_c_call_caller_fp();
233 : // 'Fast C calls' are a special type of C call where we call directly from JS
234 : // to C without an exit frame inbetween. The CEntryStub is responsible for
235 : // setting Isolate::c_entry_fp, meaning that it won't be set for fast C calls.
236 : // To keep the stack iterable, we store the FP and PC of the caller of the
237 : // fast C call on the isolate. This is guaranteed to be the topmost JS frame,
238 : // because fast C calls cannot call back into JS. We start iterating the stack
239 : // from this topmost JS frame.
240 63811 : if (fast_c_fp) {
241 : DCHECK_NE(kNullAddress, isolate->isolate_data()->fast_c_call_caller_pc());
242 : type = StackFrame::Type::OPTIMIZED;
243 864 : top_frame_type_ = type;
244 864 : state.fp = fast_c_fp;
245 864 : state.sp = sp;
246 864 : state.pc_address = isolate->isolate_data()->fast_c_call_caller_pc_address();
247 : advance_frame = false;
248 62947 : } else if (IsValidTop(top)) {
249 19346 : type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
250 19346 : top_frame_type_ = type;
251 43601 : } else if (IsValidStackAddress(fp)) {
252 : DCHECK_NE(fp, kNullAddress);
253 43601 : state.fp = fp;
254 43601 : state.sp = sp;
255 43601 : state.pc_address = StackFrame::ResolveReturnAddressLocation(
256 43601 : reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
257 :
258 : // If the top of stack is a return address to the interpreter trampoline,
259 : // then we are likely in a bytecode handler with elided frame. In that
260 : // case, set the PC properly and make sure we do not drop the frame.
261 43601 : if (IsValidStackAddress(sp)) {
262 : MSAN_MEMORY_IS_INITIALIZED(sp, kSystemPointerSize);
263 : Address tos = ReadMemoryAt(sp);
264 43601 : if (IsInterpreterFramePc(isolate, tos, &state)) {
265 20355 : state.pc_address = reinterpret_cast<Address*>(sp);
266 : advance_frame = false;
267 : }
268 : }
269 :
270 : // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
271 : // we check only that kMarkerOffset is within the stack bounds and do
272 : // compile time check that kContextOffset slot is pushed on the stack before
273 : // kMarkerOffset.
274 : STATIC_ASSERT(StandardFrameConstants::kFunctionOffset <
275 : StandardFrameConstants::kContextOffset);
276 43601 : Address frame_marker = fp + StandardFrameConstants::kFunctionOffset;
277 43601 : if (IsValidStackAddress(frame_marker)) {
278 42982 : type = StackFrame::ComputeType(this, &state);
279 42982 : top_frame_type_ = type;
280 : // We only keep the top frame if we believe it to be interpreted frame.
281 42982 : if (type != StackFrame::INTERPRETED) {
282 : advance_frame = true;
283 : }
284 : } else {
285 : // Mark the frame as OPTIMIZED if we cannot determine its type.
286 : // We chose OPTIMIZED rather than INTERPRETED because it's closer to
287 : // the original value of StackFrame::JAVA_SCRIPT here, in that JAVA_SCRIPT
288 : // referred to full-codegen frames (now removed from the tree), and
289 : // OPTIMIZED refers to turbofan frames, both of which are generated
290 : // code. INTERPRETED frames refer to bytecode.
291 : // The frame anyways will be skipped.
292 : type = StackFrame::OPTIMIZED;
293 : // Top frame is incomplete so we cannot reliably determine its type.
294 619 : top_frame_type_ = StackFrame::NONE;
295 : }
296 : } else {
297 0 : return;
298 : }
299 63811 : frame_ = SingletonFor(type, &state);
300 63811 : if (advance_frame && frame_) Advance();
301 : }
302 :
303 :
304 0 : bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
305 : Address c_entry_fp = Isolate::c_entry_fp(top);
306 62947 : if (!IsValidExitFrame(c_entry_fp)) return false;
307 : // There should be at least one JS_ENTRY stack handler.
308 : Address handler = Isolate::handler(top);
309 19346 : if (handler == kNullAddress) return false;
310 : // Check that there are no js frames on top of the native frames.
311 19346 : return c_entry_fp < handler;
312 : }
313 :
314 :
315 377165 : void SafeStackFrameIterator::AdvanceOneFrame() {
316 : DCHECK(!done());
317 377165 : StackFrame* last_frame = frame_;
318 : Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
319 : // Before advancing to the next stack frame, perform pointer validity tests.
320 377165 : if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
321 63806 : frame_ = nullptr;
322 127612 : return;
323 : }
324 :
325 : // Advance to the previous frame.
326 313359 : StackFrame::State state;
327 313359 : StackFrame::Type type = frame_->GetCallerState(&state);
328 313359 : frame_ = SingletonFor(type, &state);
329 313359 : if (!frame_) return;
330 :
331 : // Check that we have actually moved to the previous frame in the stack.
332 313359 : if (frame_->sp() <= last_sp || frame_->fp() <= last_fp) {
333 0 : frame_ = nullptr;
334 : }
335 : }
336 :
337 :
338 0 : bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
339 754330 : return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
340 : }
341 :
342 :
343 377165 : bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
344 377165 : StackFrame::State state;
345 690443 : if (frame->is_entry() || frame->is_construct_entry()) {
346 : // See EntryFrame::GetCallerState. It computes the caller FP address
347 : // and calls ExitFrame::GetStateForFramePointer on it. We need to be
348 : // sure that caller FP address is valid.
349 : Address caller_fp =
350 127774 : Memory<Address>(frame->fp() + EntryFrameConstants::kCallerFPOffset);
351 63887 : if (!IsValidExitFrame(caller_fp)) return false;
352 313278 : } else if (frame->is_arguments_adaptor()) {
353 : // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
354 : // the number of arguments is stored on stack as Smi. We need to check
355 : // that it really an Smi.
356 : Object number_of_args =
357 0 : reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->GetExpression(0);
358 0 : if (!number_of_args->IsSmi()) {
359 : return false;
360 : }
361 : }
362 313359 : frame->ComputeCallerState(&state);
363 1253436 : return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
364 313359 : SingletonFor(frame->GetCallerState(&state)) != nullptr;
365 : }
366 :
367 :
368 126834 : bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
369 126834 : if (!IsValidStackAddress(fp)) return false;
370 : Address sp = ExitFrame::ComputeStackPointer(fp);
371 19428 : if (!IsValidStackAddress(sp)) return false;
372 : StackFrame::State state;
373 : ExitFrame::FillState(fp, sp, &state);
374 : MSAN_MEMORY_IS_INITIALIZED(state.pc_address, sizeof(state.pc_address));
375 19427 : return *state.pc_address != kNullAddress;
376 : }
377 :
378 :
379 233262 : void SafeStackFrameIterator::Advance() {
380 : while (true) {
381 377165 : AdvanceOneFrame();
382 377165 : if (done()) break;
383 : ExternalCallbackScope* last_callback_scope = nullptr;
384 367259 : while (external_callback_scope_ != nullptr &&
385 : external_callback_scope_->scope_address() < frame_->fp()) {
386 : // As long as the setup of a frame is not atomic, we may happen to be
387 : // in an interval where an ExternalCallbackScope is already created,
388 : // but the frame is not yet entered. So we are actually observing
389 : // the previous frame.
390 : // Skip all the ExternalCallbackScope's that are below the current fp.
391 : last_callback_scope = external_callback_scope_;
392 17875 : external_callback_scope_ = external_callback_scope_->previous();
393 : }
394 457418 : if (frame_->is_java_script() || frame_->is_wasm()) break;
395 431871 : if (frame_->is_exit() || frame_->is_builtin_exit()) {
396 : // Some of the EXIT frames may have ExternalCallbackScope allocated on
397 : // top of them. In that case the scope corresponds to the first EXIT
398 : // frame beneath it. There may be other EXIT frames on top of the
399 : // ExternalCallbackScope, just skip them as we cannot collect any useful
400 : // information about them.
401 81 : if (last_callback_scope) {
402 81 : frame_->state_.pc_address =
403 81 : last_callback_scope->callback_entrypoint_address();
404 : }
405 : break;
406 : }
407 : }
408 233262 : }
409 :
410 :
411 : // -------------------------------------------------------------------------
412 :
413 : namespace {
414 : Code GetContainingCode(Isolate* isolate, Address pc) {
415 55255723 : return isolate->inner_pointer_to_code_cache()->GetCacheEntry(pc)->code;
416 : }
417 : } // namespace
418 :
419 1607035 : Code StackFrame::LookupCode() const {
420 : Code result = GetContainingCode(isolate(), pc());
421 : DCHECK_GE(pc(), result->InstructionStart());
422 : DCHECK_LT(pc(), result->InstructionEnd());
423 1607035 : return result;
424 : }
425 :
426 3170135 : void StackFrame::IteratePc(RootVisitor* v, Address* pc_address,
427 : Address* constant_pool_address, Code holder) {
428 3170135 : Address pc = *pc_address;
429 : DCHECK(holder->GetHeap()->GcSafeCodeContains(holder, pc));
430 6340270 : unsigned pc_offset = static_cast<unsigned>(pc - holder->InstructionStart());
431 3170135 : Object code = holder;
432 6340270 : v->VisitRootPointer(Root::kTop, nullptr, FullObjectSlot(&code));
433 6339956 : if (code == holder) return;
434 314 : holder = Code::unchecked_cast(code);
435 314 : pc = holder->InstructionStart() + pc_offset;
436 314 : *pc_address = pc;
437 : if (FLAG_enable_embedded_constant_pool && constant_pool_address) {
438 : *constant_pool_address = holder->constant_pool();
439 : }
440 : }
441 :
442 :
443 0 : void StackFrame::SetReturnAddressLocationResolver(
444 : ReturnAddressLocationResolver resolver) {
445 : DCHECK_NULL(return_address_location_resolver_);
446 0 : return_address_location_resolver_ = resolver;
447 0 : }
448 :
449 49225430 : StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
450 : State* state) {
451 : DCHECK_NE(state->fp, kNullAddress);
452 :
453 : MSAN_MEMORY_IS_INITIALIZED(
454 : state->fp + CommonFrameConstants::kContextOrFrameTypeOffset,
455 : kSystemPointerSize);
456 : intptr_t marker = Memory<intptr_t>(
457 98450860 : state->fp + CommonFrameConstants::kContextOrFrameTypeOffset);
458 49225430 : if (!iterator->can_access_heap_objects_) {
459 : // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really
460 : // means that we are being called from the profiler, which can interrupt
461 : // the VM with a signal at any arbitrary instruction, with essentially
462 : // anything on the stack. So basically none of these checks are 100%
463 : // reliable.
464 : MSAN_MEMORY_IS_INITIALIZED(
465 : state->fp + StandardFrameConstants::kFunctionOffset,
466 : kSystemPointerSize);
467 : Object maybe_function = Object(
468 1339076 : Memory<Address>(state->fp + StandardFrameConstants::kFunctionOffset));
469 669538 : if (!StackFrame::IsTypeMarker(marker)) {
470 359733 : if (maybe_function->IsSmi()) {
471 : return NATIVE;
472 359733 : } else if (IsInterpreterFramePc(iterator->isolate(), *(state->pc_address),
473 : state)) {
474 : return INTERPRETED;
475 : } else {
476 34288 : return OPTIMIZED;
477 : }
478 : }
479 : } else {
480 48555892 : Address pc = *(state->pc_address);
481 : // If the {pc} does not point into WebAssembly code we can rely on the
482 : // returned {wasm_code} to be null and fall back to {GetContainingCode}.
483 : wasm::WasmCode* wasm_code =
484 48555892 : iterator->isolate()->wasm_engine()->code_manager()->LookupCode(pc);
485 48556130 : if (wasm_code != nullptr) {
486 2829722 : switch (wasm_code->kind()) {
487 : case wasm::WasmCode::kFunction:
488 : return WASM_COMPILED;
489 : case wasm::WasmCode::kWasmToJsWrapper:
490 8365 : return WASM_TO_JS;
491 : case wasm::WasmCode::kRuntimeStub:
492 : // Some stubs, like e.g. {WasmCode::kWasmCompileLazy} build their own
493 : // specialized frame which already carries a type marker.
494 : // TODO(mstarzinger): This is only needed for the case where embedded
495 : // builtins are disabled. It can be removed once all non-embedded
496 : // builtins are gone.
497 0 : if (StackFrame::IsTypeMarker(marker)) break;
498 : return STUB;
499 : case wasm::WasmCode::kInterpreterEntry:
500 40394 : return WASM_INTERPRETER_ENTRY;
501 : default:
502 0 : UNREACHABLE();
503 : }
504 : } else {
505 : // Look up the code object to figure out the type of the stack frame.
506 : Code code_obj = GetContainingCode(iterator->isolate(), pc);
507 45726313 : if (!code_obj.is_null()) {
508 45726326 : switch (code_obj->kind()) {
509 : case Code::BUILTIN:
510 34656862 : if (StackFrame::IsTypeMarker(marker)) break;
511 27926347 : if (code_obj->is_interpreter_trampoline_builtin()) {
512 : return INTERPRETED;
513 : }
514 1480739 : if (code_obj->is_turbofanned()) {
515 : // TODO(bmeurer): We treat frames for BUILTIN Code objects as
516 : // OptimizedFrame for now (all the builtins with JavaScript
517 : // linkage are actually generated with TurboFan currently, so
518 : // this is sound).
519 : return OPTIMIZED;
520 : }
521 0 : return BUILTIN;
522 : case Code::OPTIMIZED_FUNCTION:
523 : return OPTIMIZED;
524 : case Code::WASM_FUNCTION:
525 0 : return WASM_COMPILED;
526 : case Code::WASM_TO_JS_FUNCTION:
527 0 : return WASM_TO_JS;
528 : case Code::JS_TO_WASM_FUNCTION:
529 313029 : return JS_TO_WASM;
530 : case Code::WASM_INTERPRETER_ENTRY:
531 0 : return WASM_INTERPRETER_ENTRY;
532 : case Code::C_WASM_ENTRY:
533 1309 : return C_WASM_ENTRY;
534 : default:
535 : // All other types should have an explicit marker
536 : break;
537 : }
538 : } else {
539 : return NATIVE;
540 : }
541 : }
542 : }
543 : DCHECK(StackFrame::IsTypeMarker(marker));
544 : StackFrame::Type candidate = StackFrame::MarkerToType(marker);
545 12615314 : switch (candidate) {
546 : case ENTRY:
547 : case CONSTRUCT_ENTRY:
548 : case EXIT:
549 : case BUILTIN_CONTINUATION:
550 : case JAVA_SCRIPT_BUILTIN_CONTINUATION:
551 : case JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH:
552 : case BUILTIN_EXIT:
553 : case STUB:
554 : case INTERNAL:
555 : case CONSTRUCT:
556 : case ARGUMENTS_ADAPTOR:
557 : case WASM_TO_JS:
558 : case WASM_COMPILED:
559 : case WASM_COMPILE_LAZY:
560 12615314 : return candidate;
561 : case JS_TO_WASM:
562 : case OPTIMIZED:
563 : case INTERPRETED:
564 : default:
565 : // Unoptimized and optimized JavaScript frames, including
566 : // interpreted frames, should never have a StackFrame::Type
567 : // marker. If we find one, we're likely being called from the
568 : // profiler in a bogus stack frame.
569 : return NATIVE;
570 : }
571 : }
572 :
573 :
574 : #ifdef DEBUG
575 : bool StackFrame::can_access_heap_objects() const {
576 : return iterator_->can_access_heap_objects_;
577 : }
578 : #endif
579 :
580 :
581 49182442 : StackFrame::Type StackFrame::GetCallerState(State* state) const {
582 49182442 : ComputeCallerState(state);
583 49182453 : return ComputeType(iterator_, state);
584 : }
585 :
586 :
587 0 : Address StackFrame::UnpaddedFP() const {
588 0 : return fp();
589 : }
590 :
591 0 : Code NativeFrame::unchecked_code() const { return Code(); }
592 :
593 0 : void NativeFrame::ComputeCallerState(State* state) const {
594 0 : state->sp = caller_sp();
595 0 : state->fp = Memory<Address>(fp() + CommonFrameConstants::kCallerFPOffset);
596 0 : state->pc_address = ResolveReturnAddressLocation(
597 0 : reinterpret_cast<Address*>(fp() + CommonFrameConstants::kCallerPCOffset));
598 0 : state->callee_pc_address = nullptr;
599 0 : state->constant_pool_address = nullptr;
600 0 : }
601 :
602 0 : Code EntryFrame::unchecked_code() const {
603 0 : return isolate()->heap()->builtin(Builtins::kJSEntry);
604 : }
605 :
606 :
607 81 : void EntryFrame::ComputeCallerState(State* state) const {
608 81 : GetCallerState(state);
609 81 : }
610 :
611 :
612 1601839 : StackFrame::Type EntryFrame::GetCallerState(State* state) const {
613 : const int offset = EntryFrameConstants::kCallerFPOffset;
614 3203678 : Address fp = Memory<Address>(this->fp() + offset);
615 1601839 : return ExitFrame::GetStateForFramePointer(fp, state);
616 : }
617 :
618 0 : Code ConstructEntryFrame::unchecked_code() const {
619 0 : return isolate()->heap()->builtin(Builtins::kJSConstructEntry);
620 : }
621 :
622 0 : Code ExitFrame::unchecked_code() const { UNREACHABLE(); }
623 :
624 8660669 : void ExitFrame::ComputeCallerState(State* state) const {
625 : // Set up the caller state.
626 17321338 : state->sp = caller_sp();
627 8660669 : state->fp = Memory<Address>(fp() + ExitFrameConstants::kCallerFPOffset);
628 8660669 : state->pc_address = ResolveReturnAddressLocation(
629 17321338 : reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
630 8660669 : state->callee_pc_address = nullptr;
631 : if (FLAG_enable_embedded_constant_pool) {
632 : state->constant_pool_address = reinterpret_cast<Address*>(
633 : fp() + ExitFrameConstants::kConstantPoolOffset);
634 : }
635 8660669 : }
636 :
637 :
638 155174 : void ExitFrame::Iterate(RootVisitor* v) const {
639 : // The arguments are traversed as part of the expression stack of
640 : // the calling frame.
641 155174 : IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
642 155174 : }
643 :
644 :
645 8661650 : Address ExitFrame::GetCallerStackPointer() const {
646 8661650 : return fp() + ExitFrameConstants::kCallerSPOffset;
647 : }
648 :
649 :
650 10629238 : StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
651 10629238 : if (fp == 0) return NONE;
652 : Address sp = ComputeStackPointer(fp);
653 : FillState(fp, sp, state);
654 : DCHECK_NE(*state->pc_address, kNullAddress);
655 :
656 8622203 : return ComputeFrameType(fp);
657 : }
658 :
659 0 : StackFrame::Type ExitFrame::ComputeFrameType(Address fp) {
660 : // Distinguish between between regular and builtin exit frames.
661 : // Default to EXIT in all hairy cases (e.g., when called from profiler).
662 : const int offset = ExitFrameConstants::kFrameTypeOffset;
663 17244406 : Object marker(Memory<Address>(fp + offset));
664 :
665 8622203 : if (!marker->IsSmi()) {
666 : return EXIT;
667 : }
668 :
669 : intptr_t marker_int = bit_cast<intptr_t>(marker);
670 :
671 8622202 : StackFrame::Type frame_type = static_cast<StackFrame::Type>(marker_int >> 1);
672 8622202 : if (frame_type == EXIT || frame_type == BUILTIN_EXIT) {
673 0 : return frame_type;
674 : }
675 :
676 : return EXIT;
677 : }
678 :
679 0 : Address ExitFrame::ComputeStackPointer(Address fp) {
680 : MSAN_MEMORY_IS_INITIALIZED(fp + ExitFrameConstants::kSPOffset,
681 : kSystemPointerSize);
682 17283262 : return Memory<Address>(fp + ExitFrameConstants::kSPOffset);
683 : }
684 :
685 0 : void ExitFrame::FillState(Address fp, Address sp, State* state) {
686 8622203 : state->sp = sp;
687 8622203 : state->fp = fp;
688 8641630 : state->pc_address = ResolveReturnAddressLocation(
689 17263833 : reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
690 8622203 : state->callee_pc_address = nullptr;
691 : // The constant pool recorded in the exit frame is not associated
692 : // with the pc in this state (the return address into a C entry
693 : // stub). ComputeCallerState will retrieve the constant pool
694 : // together with the associated caller pc.
695 8622203 : state->constant_pool_address = nullptr;
696 0 : }
697 :
698 61056 : JSFunction BuiltinExitFrame::function() const {
699 61056 : return JSFunction::cast(target_slot_object());
700 : }
701 :
702 61620 : Object BuiltinExitFrame::receiver() const { return receiver_slot_object(); }
703 :
704 30810 : bool BuiltinExitFrame::IsConstructor() const {
705 30810 : return !new_target_slot_object()->IsUndefined(isolate());
706 : }
707 :
708 10 : Object BuiltinExitFrame::GetParameter(int i) const {
709 : DCHECK(i >= 0 && i < ComputeParametersCount());
710 : int offset =
711 19 : BuiltinExitFrameConstants::kFirstArgumentOffset + i * kSystemPointerSize;
712 38 : return Object(Memory<Address>(fp() + offset));
713 : }
714 :
715 5 : int BuiltinExitFrame::ComputeParametersCount() const {
716 : Object argc_slot = argc_slot_object();
717 : DCHECK(argc_slot->IsSmi());
718 : // Argc also counts the receiver, target, new target, and argc itself as args,
719 : // therefore the real argument count is argc - 4.
720 14 : int argc = Smi::ToInt(argc_slot) - 4;
721 : DCHECK_GE(argc, 0);
722 5 : return argc;
723 : }
724 :
725 : namespace {
726 : void PrintIndex(StringStream* accumulator, StackFrame::PrintMode mode,
727 : int index) {
728 226 : accumulator->Add((mode == StackFrame::OVERVIEW) ? "%5d: " : "[%d]: ", index);
729 : }
730 :
731 112 : const char* StringForStackFrameType(StackFrame::Type type) {
732 112 : switch (type) {
733 : #define CASE(value, name) \
734 : case StackFrame::value: \
735 : return #name;
736 0 : STACK_FRAME_TYPE_LIST(CASE)
737 : #undef CASE
738 : default:
739 0 : UNREACHABLE();
740 : }
741 : }
742 : } // namespace
743 :
744 112 : void StackFrame::Print(StringStream* accumulator, PrintMode mode,
745 : int index) const {
746 : DisallowHeapAllocation no_gc;
747 : PrintIndex(accumulator, mode, index);
748 112 : accumulator->Add(StringForStackFrameType(type()));
749 112 : accumulator->Add(" [pc: %p]\n", reinterpret_cast<void*>(pc()));
750 112 : }
751 :
752 9 : void BuiltinExitFrame::Print(StringStream* accumulator, PrintMode mode,
753 : int index) const {
754 : DisallowHeapAllocation no_gc;
755 9 : Object receiver = this->receiver();
756 9 : JSFunction function = this->function();
757 :
758 9 : accumulator->PrintSecurityTokenIfChanged(function);
759 : PrintIndex(accumulator, mode, index);
760 9 : accumulator->Add("builtin exit frame: ");
761 9 : Code code;
762 9 : if (IsConstructor()) accumulator->Add("new ");
763 9 : accumulator->PrintFunction(function, receiver, &code);
764 :
765 9 : accumulator->Add("(this=%o", receiver);
766 :
767 : // Print the parameters.
768 : int parameters_count = ComputeParametersCount();
769 27 : for (int i = 0; i < parameters_count; i++) {
770 9 : accumulator->Add(",%o", GetParameter(i));
771 : }
772 :
773 9 : accumulator->Add(")\n\n");
774 9 : }
775 :
776 1587427 : Address StandardFrame::GetExpressionAddress(int n) const {
777 : const int offset = StandardFrameConstants::kExpressionsOffset;
778 1587427 : return fp() + offset - n * kSystemPointerSize;
779 : }
780 :
781 58608093 : Address InterpretedFrame::GetExpressionAddress(int n) const {
782 : const int offset = InterpreterFrameConstants::kExpressionsOffset;
783 58608093 : return fp() + offset - n * kSystemPointerSize;
784 : }
785 :
786 0 : Script StandardFrame::script() const {
787 : // This should only be called on frames which override this method.
788 0 : UNREACHABLE();
789 : return Script();
790 : }
791 :
792 0 : Object StandardFrame::receiver() const {
793 0 : return ReadOnlyRoots(isolate()).undefined_value();
794 : }
795 :
796 176 : Object StandardFrame::context() const {
797 176 : return ReadOnlyRoots(isolate()).undefined_value();
798 : }
799 :
800 808 : int StandardFrame::position() const {
801 808 : AbstractCode code = AbstractCode::cast(LookupCode());
802 808 : int code_offset = static_cast<int>(pc() - code->InstructionStart());
803 808 : return code->SourcePosition(code_offset);
804 : }
805 :
806 0 : int StandardFrame::ComputeExpressionsCount() const {
807 21 : Address base = GetExpressionAddress(0);
808 21 : Address limit = sp() - kSystemPointerSize;
809 : DCHECK(base >= limit); // stack grows downwards
810 : // Include register-allocated locals in number of expressions.
811 21 : return static_cast<int>((base - limit) / kSystemPointerSize);
812 : }
813 :
814 0 : Object StandardFrame::GetParameter(int index) const {
815 : // StandardFrame does not define any parameters.
816 0 : UNREACHABLE();
817 : }
818 :
819 0 : int StandardFrame::ComputeParametersCount() const { return 0; }
820 :
821 40835163 : void StandardFrame::ComputeCallerState(State* state) const {
822 81670326 : state->sp = caller_sp();
823 40835163 : state->fp = caller_fp();
824 40835163 : state->pc_address = ResolveReturnAddressLocation(
825 40835163 : reinterpret_cast<Address*>(ComputePCAddress(fp())));
826 40835163 : state->callee_pc_address = pc_address();
827 : state->constant_pool_address =
828 40835163 : reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
829 40835163 : }
830 :
831 :
832 0 : bool StandardFrame::IsConstructor() const { return false; }
833 :
834 0 : void StandardFrame::Summarize(std::vector<FrameSummary>* functions) const {
835 : // This should only be called on frames which override this method.
836 0 : UNREACHABLE();
837 : }
838 :
839 700732 : void StandardFrame::IterateCompiledFrame(RootVisitor* v) const {
840 : // Make sure that we're not doing "safe" stack frame iteration. We cannot
841 : // possibly find pointers in optimized frames in that state.
842 : DCHECK(can_access_heap_objects());
843 :
844 : // Find the code and compute the safepoint information.
845 : Address inner_pointer = pc();
846 : const wasm::WasmCode* wasm_code =
847 700732 : isolate()->wasm_engine()->code_manager()->LookupCode(inner_pointer);
848 : SafepointEntry safepoint_entry;
849 : uint32_t stack_slots;
850 : Code code;
851 : bool has_tagged_params = false;
852 : uint32_t tagged_parameter_slots = 0;
853 700732 : if (wasm_code != nullptr) {
854 : SafepointTable table(wasm_code->instruction_start(),
855 : wasm_code->safepoint_table_offset(),
856 11799 : wasm_code->stack_slots());
857 11799 : safepoint_entry = table.FindEntry(inner_pointer);
858 : stack_slots = wasm_code->stack_slots();
859 11799 : has_tagged_params = wasm_code->kind() != wasm::WasmCode::kFunction;
860 : tagged_parameter_slots = wasm_code->tagged_parameter_slots();
861 : } else {
862 : InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
863 688933 : isolate()->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
864 688933 : if (!entry->safepoint_entry.is_valid()) {
865 89692 : entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
866 : DCHECK(entry->safepoint_entry.is_valid());
867 : } else {
868 : DCHECK(entry->safepoint_entry.Equals(
869 : entry->code->GetSafepointEntry(inner_pointer)));
870 : }
871 :
872 688933 : code = entry->code;
873 688933 : safepoint_entry = entry->safepoint_entry;
874 : stack_slots = code->stack_slots();
875 : has_tagged_params = code->has_tagged_params();
876 : }
877 700732 : uint32_t slot_space = stack_slots * kSystemPointerSize;
878 :
879 : // Determine the fixed header and spill slot area size.
880 : int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp;
881 : intptr_t marker =
882 1401464 : Memory<intptr_t>(fp() + CommonFrameConstants::kContextOrFrameTypeOffset);
883 700732 : if (StackFrame::IsTypeMarker(marker)) {
884 : StackFrame::Type candidate = StackFrame::MarkerToType(marker);
885 140194 : switch (candidate) {
886 : case ENTRY:
887 : case CONSTRUCT_ENTRY:
888 : case EXIT:
889 : case BUILTIN_CONTINUATION:
890 : case JAVA_SCRIPT_BUILTIN_CONTINUATION:
891 : case JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH:
892 : case BUILTIN_EXIT:
893 : case ARGUMENTS_ADAPTOR:
894 : case STUB:
895 : case INTERNAL:
896 : case CONSTRUCT:
897 : case JS_TO_WASM:
898 : case C_WASM_ENTRY:
899 : frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
900 128395 : break;
901 : case WASM_TO_JS:
902 : case WASM_COMPILED:
903 : case WASM_INTERPRETER_ENTRY:
904 : case WASM_COMPILE_LAZY:
905 : frame_header_size = WasmCompiledFrameConstants::kFixedFrameSizeFromFp;
906 : break;
907 : case OPTIMIZED:
908 : case INTERPRETED:
909 : case BUILTIN:
910 : // These frame types have a context, but they are actually stored
911 : // in the place on the stack that one finds the frame type.
912 0 : UNREACHABLE();
913 : break;
914 : case NATIVE:
915 : case NONE:
916 : case NUMBER_OF_TYPES:
917 : case MANUAL:
918 0 : UNREACHABLE();
919 : break;
920 : }
921 : }
922 : slot_space -=
923 700732 : (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp);
924 :
925 700732 : FullObjectSlot frame_header_base(&Memory<Address>(fp() - frame_header_size));
926 : FullObjectSlot frame_header_limit(
927 : &Memory<Address>(fp() - StandardFrameConstants::kCPSlotSize));
928 : FullObjectSlot parameters_base(&Memory<Address>(sp()));
929 700732 : FullObjectSlot parameters_limit(frame_header_base.address() - slot_space);
930 :
931 : // Skip saved double registers.
932 700732 : if (safepoint_entry.has_doubles()) {
933 : // Number of doubles not known at snapshot time.
934 : DCHECK(!isolate()->serializer_enabled());
935 0 : parameters_base +=
936 : RegisterConfiguration::Default()->num_allocatable_double_registers() *
937 : kDoubleSize / kSystemPointerSize;
938 : }
939 :
940 : // Visit the registers that contain pointers if any.
941 700732 : if (safepoint_entry.HasRegisters()) {
942 0 : for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
943 0 : if (safepoint_entry.HasRegisterAt(i)) {
944 : int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
945 : v->VisitRootPointer(Root::kTop, nullptr,
946 0 : parameters_base + reg_stack_index);
947 : }
948 : }
949 : // Skip the words containing the register values.
950 : parameters_base += kNumSafepointRegisters;
951 : }
952 :
953 : // We're done dealing with the register bits.
954 : uint8_t* safepoint_bits = safepoint_entry.bits();
955 : safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
956 :
957 : // Visit the rest of the parameters if they are tagged.
958 700732 : if (has_tagged_params) {
959 : v->VisitRootPointers(Root::kTop, nullptr, parameters_base,
960 688669 : parameters_limit);
961 : }
962 :
963 : // Visit pointer spill slots and locals.
964 11248610 : for (unsigned index = 0; index < stack_slots; index++) {
965 5273939 : int byte_index = index >> kBitsPerByteLog2;
966 5273939 : int bit_index = index & (kBitsPerByte - 1);
967 5273939 : if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
968 1969218 : v->VisitRootPointer(Root::kTop, nullptr, parameters_limit + index);
969 : }
970 : }
971 :
972 : // Visit tagged parameters that have been passed to the function of this
973 : // frame. Conceptionally these parameters belong to the parent frame. However,
974 : // the exact count is only known by this frame (in the presence of tail calls,
975 : // this information cannot be derived from the call site).
976 700732 : if (tagged_parameter_slots > 0) {
977 270 : FullObjectSlot tagged_parameter_base(&Memory<Address>(caller_sp()));
978 : FullObjectSlot tagged_parameter_limit =
979 540 : tagged_parameter_base + tagged_parameter_slots;
980 :
981 : v->VisitRootPointers(Root::kTop, nullptr, tagged_parameter_base,
982 270 : tagged_parameter_limit);
983 : }
984 :
985 : // For the off-heap code cases, we can skip this.
986 700732 : if (!code.is_null()) {
987 : // Visit the return address in the callee and incoming arguments.
988 688933 : IteratePc(v, pc_address(), constant_pool_address(), code);
989 : }
990 :
991 : // If this frame has JavaScript ABI, visit the context (in stub and JS
992 : // frames) and the function (in JS frames). If it has WebAssembly ABI, visit
993 : // the instance object.
994 : v->VisitRootPointers(Root::kTop, nullptr, frame_header_base,
995 700732 : frame_header_limit);
996 700732 : }
997 :
998 140240 : void StubFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); }
999 :
1000 0 : Code StubFrame::unchecked_code() const {
1001 0 : return isolate()->FindCodeObject(pc());
1002 : }
1003 :
1004 :
1005 7161692 : Address StubFrame::GetCallerStackPointer() const {
1006 7161692 : return fp() + ExitFrameConstants::kCallerSPOffset;
1007 : }
1008 :
1009 45604 : int StubFrame::LookupExceptionHandlerInTable(int* stack_slots) {
1010 45604 : Code code = LookupCode();
1011 : DCHECK(code->is_turbofanned());
1012 : DCHECK_EQ(code->kind(), Code::BUILTIN);
1013 45604 : HandlerTable table(code);
1014 91208 : int pc_offset = static_cast<int>(pc() - code->InstructionStart());
1015 45604 : *stack_slots = code->stack_slots();
1016 45604 : return table.LookupReturn(pc_offset);
1017 : }
1018 :
1019 554474 : void OptimizedFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); }
1020 :
1021 2138 : void JavaScriptFrame::SetParameterValue(int index, Object value) const {
1022 2138 : Memory<Address>(GetParameterSlot(index)) = value->ptr();
1023 2138 : }
1024 :
1025 7439651 : bool JavaScriptFrame::IsConstructor() const {
1026 : Address fp = caller_fp();
1027 7439651 : if (has_adapted_arguments()) {
1028 : // Skip the arguments adaptor frame and look at the real caller.
1029 555645 : fp = Memory<Address>(fp + StandardFrameConstants::kCallerFPOffset);
1030 : }
1031 7439651 : return IsConstructFrame(fp);
1032 : }
1033 :
1034 :
1035 0 : bool JavaScriptFrame::HasInlinedFrames() const {
1036 : std::vector<SharedFunctionInfo> functions;
1037 0 : GetFunctions(&functions);
1038 0 : return functions.size() > 1;
1039 : }
1040 :
1041 0 : Code JavaScriptFrame::unchecked_code() const { return function()->code(); }
1042 :
1043 25710 : int OptimizedFrame::ComputeParametersCount() const {
1044 : Code code = LookupCode();
1045 25710 : if (code->kind() == Code::BUILTIN) {
1046 : return static_cast<int>(
1047 380 : Memory<intptr_t>(fp() + OptimizedBuiltinFrameConstants::kArgCOffset));
1048 : } else {
1049 25520 : return JavaScriptFrame::ComputeParametersCount();
1050 : }
1051 : }
1052 :
1053 38178906 : Address JavaScriptFrame::GetCallerStackPointer() const {
1054 38178906 : return fp() + StandardFrameConstants::kCallerSPOffset;
1055 : }
1056 :
1057 266739 : void JavaScriptFrame::GetFunctions(
1058 : std::vector<SharedFunctionInfo>* functions) const {
1059 : DCHECK(functions->empty());
1060 800217 : functions->push_back(function()->shared());
1061 266739 : }
1062 :
1063 104441 : void JavaScriptFrame::GetFunctions(
1064 : std::vector<Handle<SharedFunctionInfo>>* functions) const {
1065 : DCHECK(functions->empty());
1066 : std::vector<SharedFunctionInfo> raw_functions;
1067 104441 : GetFunctions(&raw_functions);
1068 208896 : for (const auto& raw_function : raw_functions) {
1069 104455 : functions->push_back(
1070 208910 : Handle<SharedFunctionInfo>(raw_function, function()->GetIsolate()));
1071 : }
1072 104441 : }
1073 :
1074 213805 : void JavaScriptFrame::Summarize(std::vector<FrameSummary>* functions) const {
1075 : DCHECK(functions->empty());
1076 213805 : Code code = LookupCode();
1077 427610 : int offset = static_cast<int>(pc() - code->InstructionStart());
1078 213805 : AbstractCode abstract_code = AbstractCode::cast(code);
1079 213805 : Handle<FixedArray> params = GetParameters();
1080 : FrameSummary::JavaScriptFrameSummary summary(
1081 641415 : isolate(), receiver(), function(), abstract_code, offset, IsConstructor(),
1082 641415 : *params);
1083 213805 : functions->push_back(summary);
1084 213805 : }
1085 :
1086 28322026 : JSFunction JavaScriptFrame::function() const {
1087 28322026 : return JSFunction::cast(function_slot_object());
1088 : }
1089 :
1090 109588 : Object JavaScriptFrame::unchecked_function() const {
1091 : // During deoptimization of an optimized function, we may have yet to
1092 : // materialize some closures on the stack. The arguments marker object
1093 : // marks this case.
1094 : DCHECK(function_slot_object()->IsJSFunction() ||
1095 : ReadOnlyRoots(isolate()).arguments_marker() == function_slot_object());
1096 109588 : return function_slot_object();
1097 : }
1098 :
1099 5934194 : Object JavaScriptFrame::receiver() const { return GetParameter(-1); }
1100 :
1101 489011 : Object JavaScriptFrame::context() const {
1102 : const int offset = StandardFrameConstants::kContextOffset;
1103 978022 : Object maybe_result(Memory<Address>(fp() + offset));
1104 : DCHECK(!maybe_result->IsSmi());
1105 489011 : return maybe_result;
1106 : }
1107 :
1108 0 : Script JavaScriptFrame::script() const {
1109 0 : return Script::cast(function()->shared()->script());
1110 : }
1111 :
1112 0 : int JavaScriptFrame::LookupExceptionHandlerInTable(
1113 : int* stack_depth, HandlerTable::CatchPrediction* prediction) {
1114 : DCHECK(!LookupCode()->has_handler_table());
1115 : DCHECK(!LookupCode()->is_optimized_code());
1116 0 : return -1;
1117 : }
1118 :
1119 0 : void JavaScriptFrame::PrintFunctionAndOffset(JSFunction function,
1120 : AbstractCode code, int code_offset,
1121 : FILE* file,
1122 : bool print_line_number) {
1123 0 : PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
1124 0 : function->PrintName(file);
1125 0 : PrintF(file, "+%d", code_offset);
1126 0 : if (print_line_number) {
1127 0 : SharedFunctionInfo shared = function->shared();
1128 0 : int source_pos = code->SourcePosition(code_offset);
1129 0 : Object maybe_script = shared->script();
1130 0 : if (maybe_script->IsScript()) {
1131 0 : Script script = Script::cast(maybe_script);
1132 0 : int line = script->GetLineNumber(source_pos) + 1;
1133 : Object script_name_raw = script->name();
1134 0 : if (script_name_raw->IsString()) {
1135 0 : String script_name = String::cast(script->name());
1136 : std::unique_ptr<char[]> c_script_name =
1137 0 : script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1138 0 : PrintF(file, " at %s:%d", c_script_name.get(), line);
1139 : } else {
1140 0 : PrintF(file, " at <unknown>:%d", line);
1141 : }
1142 : } else {
1143 0 : PrintF(file, " at <unknown>:<unknown>");
1144 : }
1145 : }
1146 0 : }
1147 :
1148 0 : void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
1149 : bool print_line_number) {
1150 : // constructor calls
1151 : DisallowHeapAllocation no_allocation;
1152 0 : JavaScriptFrameIterator it(isolate);
1153 0 : while (!it.done()) {
1154 0 : if (it.frame()->is_java_script()) {
1155 : JavaScriptFrame* frame = it.frame();
1156 0 : if (frame->IsConstructor()) PrintF(file, "new ");
1157 0 : JSFunction function = frame->function();
1158 : int code_offset = 0;
1159 0 : if (frame->is_interpreted()) {
1160 : InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame);
1161 : code_offset = iframe->GetBytecodeOffset();
1162 : } else {
1163 0 : Code code = frame->unchecked_code();
1164 0 : code_offset = static_cast<int>(frame->pc() - code->InstructionStart());
1165 : }
1166 0 : PrintFunctionAndOffset(function, function->abstract_code(), code_offset,
1167 0 : file, print_line_number);
1168 0 : if (print_args) {
1169 : // function arguments
1170 : // (we are intentionally only printing the actually
1171 : // supplied parameters, not all parameters required)
1172 0 : PrintF(file, "(this=");
1173 0 : frame->receiver()->ShortPrint(file);
1174 0 : const int length = frame->ComputeParametersCount();
1175 0 : for (int i = 0; i < length; i++) {
1176 0 : PrintF(file, ", ");
1177 0 : frame->GetParameter(i)->ShortPrint(file);
1178 : }
1179 0 : PrintF(file, ")");
1180 : }
1181 : break;
1182 : }
1183 0 : it.Advance();
1184 : }
1185 0 : }
1186 :
1187 0 : void JavaScriptFrame::CollectFunctionAndOffsetForICStats(JSFunction function,
1188 : AbstractCode code,
1189 : int code_offset) {
1190 : auto ic_stats = ICStats::instance();
1191 : ICInfo& ic_info = ic_stats->Current();
1192 0 : SharedFunctionInfo shared = function->shared();
1193 :
1194 0 : ic_info.function_name = ic_stats->GetOrCacheFunctionName(function);
1195 0 : ic_info.script_offset = code_offset;
1196 :
1197 0 : int source_pos = code->SourcePosition(code_offset);
1198 0 : Object maybe_script = shared->script();
1199 0 : if (maybe_script->IsScript()) {
1200 0 : Script script = Script::cast(maybe_script);
1201 0 : ic_info.line_num = script->GetLineNumber(source_pos) + 1;
1202 0 : ic_info.script_name = ic_stats->GetOrCacheScriptName(script);
1203 : }
1204 0 : }
1205 :
1206 7657177 : Object JavaScriptFrame::GetParameter(int index) const {
1207 7657177 : return Object(Memory<Address>(GetParameterSlot(index)));
1208 : }
1209 :
1210 6133862 : int JavaScriptFrame::ComputeParametersCount() const {
1211 : DCHECK(can_access_heap_objects() &&
1212 : isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
1213 12267724 : return function()->shared()->internal_formal_parameter_count();
1214 : }
1215 :
1216 7733249 : Handle<FixedArray> JavaScriptFrame::GetParameters() const {
1217 7733249 : if (V8_LIKELY(!FLAG_detailed_error_stack_trace)) {
1218 : return isolate()->factory()->empty_fixed_array();
1219 : }
1220 60 : int param_count = ComputeParametersCount();
1221 : Handle<FixedArray> parameters =
1222 60 : isolate()->factory()->NewFixedArray(param_count);
1223 170 : for (int i = 0; i < param_count; i++) {
1224 110 : parameters->set(i, GetParameter(i));
1225 : }
1226 :
1227 60 : return parameters;
1228 : }
1229 :
1230 40 : int JavaScriptBuiltinContinuationFrame::ComputeParametersCount() const {
1231 : // Assert that the first allocatable register is also the argument count
1232 : // register.
1233 : DCHECK_EQ(RegisterConfiguration::Default()->GetAllocatableGeneralCode(0),
1234 : kJavaScriptCallArgCountRegister.code());
1235 : Object argc_object(
1236 80 : Memory<Address>(fp() + BuiltinContinuationFrameConstants::kArgCOffset));
1237 40 : return Smi::ToInt(argc_object);
1238 : }
1239 :
1240 8 : intptr_t JavaScriptBuiltinContinuationFrame::GetSPToFPDelta() const {
1241 : Address height_slot =
1242 8 : fp() + BuiltinContinuationFrameConstants::kFrameSPtoFPDeltaAtDeoptimize;
1243 16 : intptr_t height = Smi::ToInt(Smi(Memory<Address>(height_slot)));
1244 8 : return height;
1245 : }
1246 :
1247 214 : Object JavaScriptBuiltinContinuationFrame::context() const {
1248 : return Object(Memory<Address>(
1249 428 : fp() + BuiltinContinuationFrameConstants::kBuiltinContextOffset));
1250 : }
1251 :
1252 8 : void JavaScriptBuiltinContinuationWithCatchFrame::SetException(
1253 : Object exception) {
1254 : Address exception_argument_slot =
1255 : fp() + JavaScriptFrameConstants::kLastParameterOffset +
1256 8 : kSystemPointerSize; // Skip over return value slot.
1257 :
1258 : // Only allow setting exception if previous value was the hole.
1259 16 : CHECK_EQ(ReadOnlyRoots(isolate()).the_hole_value(),
1260 : Object(Memory<Address>(exception_argument_slot)));
1261 8 : Memory<Address>(exception_argument_slot) = exception->ptr();
1262 8 : }
1263 :
1264 7733249 : FrameSummary::JavaScriptFrameSummary::JavaScriptFrameSummary(
1265 : Isolate* isolate, Object receiver, JSFunction function,
1266 : AbstractCode abstract_code, int code_offset, bool is_constructor,
1267 : FixedArray parameters)
1268 : : FrameSummaryBase(isolate, FrameSummary::JAVA_SCRIPT),
1269 : receiver_(receiver, isolate),
1270 : function_(function, isolate),
1271 : abstract_code_(abstract_code, isolate),
1272 : code_offset_(code_offset),
1273 : is_constructor_(is_constructor),
1274 7733249 : parameters_(parameters, isolate) {
1275 : DCHECK(abstract_code->IsBytecodeArray() ||
1276 : Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION);
1277 : // TODO(v8:8510): Move this to the SourcePosition getter.
1278 7733259 : if (FLAG_enable_lazy_source_positions && abstract_code->IsBytecodeArray()) {
1279 : SharedFunctionInfo::EnsureSourcePositionsAvailable(
1280 10 : isolate, handle(function->shared(), isolate));
1281 : }
1282 7733249 : }
1283 :
1284 312726 : bool FrameSummary::JavaScriptFrameSummary::is_subject_to_debugging() const {
1285 312726 : return function()->shared()->IsSubjectToDebugging();
1286 : }
1287 :
1288 0 : int FrameSummary::JavaScriptFrameSummary::SourcePosition() const {
1289 1081294 : return abstract_code()->SourcePosition(code_offset());
1290 : }
1291 :
1292 0 : int FrameSummary::JavaScriptFrameSummary::SourceStatementPosition() const {
1293 46333 : return abstract_code()->SourceStatementPosition(code_offset());
1294 : }
1295 :
1296 1432061 : Handle<Object> FrameSummary::JavaScriptFrameSummary::script() const {
1297 2864122 : return handle(function_->shared()->script(), isolate());
1298 : }
1299 :
1300 0 : Handle<String> FrameSummary::JavaScriptFrameSummary::FunctionName() const {
1301 260952 : return JSFunction::GetDebugName(function_);
1302 : }
1303 :
1304 0 : Handle<Context> FrameSummary::JavaScriptFrameSummary::native_context() const {
1305 0 : return handle(function_->context()->native_context(), isolate());
1306 : }
1307 :
1308 0 : FrameSummary::WasmFrameSummary::WasmFrameSummary(
1309 : Isolate* isolate, FrameSummary::Kind kind,
1310 : Handle<WasmInstanceObject> instance, bool at_to_number_conversion)
1311 : : FrameSummaryBase(isolate, kind),
1312 : wasm_instance_(instance),
1313 305510 : at_to_number_conversion_(at_to_number_conversion) {}
1314 :
1315 832 : Handle<Object> FrameSummary::WasmFrameSummary::receiver() const {
1316 832 : return wasm_instance_->GetIsolate()->global_proxy();
1317 : }
1318 :
1319 : #define WASM_SUMMARY_DISPATCH(type, name) \
1320 : type FrameSummary::WasmFrameSummary::name() const { \
1321 : DCHECK(kind() == Kind::WASM_COMPILED || kind() == Kind::WASM_INTERPRETED); \
1322 : return kind() == Kind::WASM_COMPILED \
1323 : ? static_cast<const WasmCompiledFrameSummary*>(this)->name() \
1324 : : static_cast<const WasmInterpretedFrameSummary*>(this) \
1325 : ->name(); \
1326 : }
1327 :
1328 151775 : WASM_SUMMARY_DISPATCH(uint32_t, function_index)
1329 150943 : WASM_SUMMARY_DISPATCH(int, byte_offset)
1330 :
1331 : #undef WASM_SUMMARY_DISPATCH
1332 :
1333 150943 : int FrameSummary::WasmFrameSummary::SourcePosition() const {
1334 : Handle<WasmModuleObject> module_object(wasm_instance()->module_object(),
1335 : isolate());
1336 301886 : return WasmModuleObject::GetSourcePosition(module_object, function_index(),
1337 : byte_offset(),
1338 150943 : at_to_number_conversion());
1339 : }
1340 :
1341 150855 : Handle<Script> FrameSummary::WasmFrameSummary::script() const {
1342 : return handle(wasm_instance()->module_object()->script(),
1343 150855 : wasm_instance()->GetIsolate());
1344 : }
1345 :
1346 832 : Handle<String> FrameSummary::WasmFrameSummary::FunctionName() const {
1347 : Handle<WasmModuleObject> module_object(wasm_instance()->module_object(),
1348 : isolate());
1349 : return WasmModuleObject::GetFunctionName(isolate(), module_object,
1350 832 : function_index());
1351 : }
1352 :
1353 0 : Handle<Context> FrameSummary::WasmFrameSummary::native_context() const {
1354 0 : return handle(wasm_instance()->native_context(), isolate());
1355 : }
1356 :
1357 0 : FrameSummary::WasmCompiledFrameSummary::WasmCompiledFrameSummary(
1358 : Isolate* isolate, Handle<WasmInstanceObject> instance, wasm::WasmCode* code,
1359 : int code_offset, bool at_to_number_conversion)
1360 : : WasmFrameSummary(isolate, WASM_COMPILED, instance,
1361 : at_to_number_conversion),
1362 : code_(code),
1363 0 : code_offset_(code_offset) {}
1364 :
1365 155191 : uint32_t FrameSummary::WasmCompiledFrameSummary::function_index() const {
1366 155191 : return code()->index();
1367 : }
1368 :
1369 151767 : int FrameSummary::WasmCompiledFrameSummary::GetWasmSourcePosition(
1370 : const wasm::WasmCode* code, int offset) {
1371 : int position = 0;
1372 : // Subtract one because the current PC is one instruction after the call site.
1373 : offset--;
1374 722850 : for (SourcePositionTableIterator iterator(code->source_positions());
1375 361425 : !iterator.done() && iterator.code_offset() <= offset;
1376 209658 : iterator.Advance()) {
1377 : position = iterator.source_position().ScriptOffset();
1378 : }
1379 151767 : return position;
1380 : }
1381 :
1382 0 : int FrameSummary::WasmCompiledFrameSummary::byte_offset() const {
1383 150039 : return GetWasmSourcePosition(code_, code_offset());
1384 : }
1385 :
1386 0 : FrameSummary::WasmInterpretedFrameSummary::WasmInterpretedFrameSummary(
1387 : Isolate* isolate, Handle<WasmInstanceObject> instance,
1388 : uint32_t function_index, int byte_offset)
1389 : : WasmFrameSummary(isolate, WASM_INTERPRETED, instance, false),
1390 : function_index_(function_index),
1391 0 : byte_offset_(byte_offset) {}
1392 :
1393 28952193 : FrameSummary::~FrameSummary() {
1394 : #define FRAME_SUMMARY_DESTR(kind, type, field, desc) \
1395 : case kind: \
1396 : field.~type(); \
1397 : break;
1398 20324979 : switch (base_.kind()) {
1399 : FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_DESTR)
1400 : default:
1401 0 : UNREACHABLE();
1402 : }
1403 : #undef FRAME_SUMMARY_DESTR
1404 8627214 : }
1405 :
1406 909685 : FrameSummary FrameSummary::GetTop(const StandardFrame* frame) {
1407 909685 : std::vector<FrameSummary> frames;
1408 909685 : frame->Summarize(&frames);
1409 : DCHECK_LT(0, frames.size());
1410 1819370 : return frames.back();
1411 : }
1412 :
1413 0 : FrameSummary FrameSummary::GetBottom(const StandardFrame* frame) {
1414 0 : return Get(frame, 0);
1415 : }
1416 :
1417 192 : FrameSummary FrameSummary::GetSingle(const StandardFrame* frame) {
1418 192 : std::vector<FrameSummary> frames;
1419 192 : frame->Summarize(&frames);
1420 : DCHECK_EQ(1, frames.size());
1421 384 : return frames.front();
1422 : }
1423 :
1424 511439 : FrameSummary FrameSummary::Get(const StandardFrame* frame, int index) {
1425 : DCHECK_LE(0, index);
1426 511439 : std::vector<FrameSummary> frames;
1427 511439 : frame->Summarize(&frames);
1428 : DCHECK_GT(frames.size(), index);
1429 1534317 : return frames[index];
1430 : }
1431 :
1432 : #define FRAME_SUMMARY_DISPATCH(ret, name) \
1433 : ret FrameSummary::name() const { \
1434 : switch (base_.kind()) { \
1435 : case JAVA_SCRIPT: \
1436 : return java_script_summary_.name(); \
1437 : case WASM_COMPILED: \
1438 : return wasm_compiled_summary_.name(); \
1439 : case WASM_INTERPRETED: \
1440 : return wasm_interpreted_summary_.name(); \
1441 : default: \
1442 : UNREACHABLE(); \
1443 : return ret{}; \
1444 : } \
1445 : }
1446 :
1447 261784 : FRAME_SUMMARY_DISPATCH(Handle<Object>, receiver)
1448 351652 : FRAME_SUMMARY_DISPATCH(int, code_offset)
1449 261784 : FRAME_SUMMARY_DISPATCH(bool, is_constructor)
1450 314002 : FRAME_SUMMARY_DISPATCH(bool, is_subject_to_debugging)
1451 1582916 : FRAME_SUMMARY_DISPATCH(Handle<Object>, script)
1452 2313531 : FRAME_SUMMARY_DISPATCH(int, SourcePosition)
1453 92666 : FRAME_SUMMARY_DISPATCH(int, SourceStatementPosition)
1454 261872 : FRAME_SUMMARY_DISPATCH(Handle<String>, FunctionName)
1455 0 : FRAME_SUMMARY_DISPATCH(Handle<Context>, native_context)
1456 :
1457 : #undef FRAME_SUMMARY_DISPATCH
1458 :
1459 1505457 : void OptimizedFrame::Summarize(std::vector<FrameSummary>* frames) const {
1460 : DCHECK(frames->empty());
1461 : DCHECK(is_optimized());
1462 :
1463 : // Delegate to JS frame in absence of turbofan deoptimization.
1464 : // TODO(turbofan): Revisit once we support deoptimization across the board.
1465 : Code code = LookupCode();
1466 1505457 : if (code->kind() == Code::BUILTIN) {
1467 213765 : return JavaScriptFrame::Summarize(frames);
1468 : }
1469 :
1470 1291692 : int deopt_index = Safepoint::kNoDeoptimizationIndex;
1471 1291692 : DeoptimizationData const data = GetDeoptimizationData(&deopt_index);
1472 1291692 : if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
1473 0 : CHECK(data.is_null());
1474 0 : FATAL("Missing deoptimization information for OptimizedFrame::Summarize.");
1475 : }
1476 :
1477 : // Prepare iteration over translation. Note that the below iteration might
1478 : // materialize objects without storing them back to the Isolate, this will
1479 : // lead to objects being re-materialized again for each summary.
1480 1291692 : TranslatedState translated(this);
1481 1291692 : translated.Prepare(fp());
1482 :
1483 : // We create the summary in reverse order because the frames
1484 : // in the deoptimization translation are ordered bottom-to-top.
1485 1291692 : bool is_constructor = IsConstructor();
1486 3049542 : for (auto it = translated.begin(); it != translated.end(); it++) {
1487 1931825 : if (it->kind() == TranslatedFrame::kInterpretedFunction ||
1488 1930407 : it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation ||
1489 : it->kind() ==
1490 : TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) {
1491 : Handle<SharedFunctionInfo> shared_info = it->shared_info();
1492 :
1493 : // The translation commands are ordered and the function is always
1494 : // at the first position, and the receiver is next.
1495 : TranslatedFrame::iterator translated_values = it->begin();
1496 :
1497 : // Get or materialize the correct function in the optimized frame.
1498 : Handle<JSFunction> function =
1499 1585347 : Handle<JSFunction>::cast(translated_values->GetValue());
1500 : translated_values++;
1501 :
1502 : // Get or materialize the correct receiver in the optimized frame.
1503 1585347 : Handle<Object> receiver = translated_values->GetValue();
1504 : translated_values++;
1505 :
1506 : // Determine the underlying code object and the position within it from
1507 : // the translation corresponding to the frame type in question.
1508 : Handle<AbstractCode> abstract_code;
1509 : unsigned code_offset;
1510 1585347 : if (it->kind() == TranslatedFrame::kJavaScriptBuiltinContinuation ||
1511 : it->kind() ==
1512 : TranslatedFrame::kJavaScriptBuiltinContinuationWithCatch) {
1513 : code_offset = 0;
1514 : abstract_code =
1515 2944 : handle(AbstractCode::cast(isolate()->builtins()->builtin(
1516 1472 : Builtins::GetBuiltinFromBailoutId(it->node_id()))),
1517 : isolate());
1518 : } else {
1519 : DCHECK_EQ(it->kind(), TranslatedFrame::kInterpretedFunction);
1520 1583875 : code_offset = it->node_id().ToInt(); // Points to current bytecode.
1521 3167750 : abstract_code = handle(shared_info->abstract_code(), isolate());
1522 : }
1523 :
1524 : // Append full summary of the encountered JS frame.
1525 1585347 : Handle<FixedArray> params = GetParameters();
1526 : FrameSummary::JavaScriptFrameSummary summary(
1527 : isolate(), *receiver, *function, *abstract_code, code_offset,
1528 3170694 : is_constructor, *params);
1529 1585347 : frames->push_back(summary);
1530 : is_constructor = false;
1531 172503 : } else if (it->kind() == TranslatedFrame::kConstructStub) {
1532 : // The next encountered JS frame will be marked as a constructor call.
1533 : DCHECK(!is_constructor);
1534 : is_constructor = true;
1535 : }
1536 : }
1537 : }
1538 :
1539 :
1540 3378183 : int OptimizedFrame::LookupExceptionHandlerInTable(
1541 : int* stack_slots, HandlerTable::CatchPrediction* prediction) {
1542 : // We cannot perform exception prediction on optimized code. Instead, we need
1543 : // to use FrameSummary to find the corresponding code offset in unoptimized
1544 : // code to perform prediction there.
1545 : DCHECK_NULL(prediction);
1546 3378183 : Code code = LookupCode();
1547 3378183 : HandlerTable table(code);
1548 6756366 : int pc_offset = static_cast<int>(pc() - code->InstructionStart());
1549 6710813 : if (stack_slots) *stack_slots = code->stack_slots();
1550 :
1551 : // When the return pc has been replaced by a trampoline there won't be
1552 : // a handler for this trampoline. Thus we need to use the return pc that
1553 : // _used to be_ on the stack to get the right ExceptionHandler.
1554 6103553 : if (code->kind() == Code::OPTIMIZED_FUNCTION &&
1555 2725370 : code->marked_for_deoptimization()) {
1556 5384 : SafepointTable safepoints(code);
1557 5384 : pc_offset = safepoints.find_return_pc(pc_offset);
1558 : }
1559 3378183 : return table.LookupReturn(pc_offset);
1560 : }
1561 :
1562 2654198 : DeoptimizationData OptimizedFrame::GetDeoptimizationData(
1563 : int* deopt_index) const {
1564 : DCHECK(is_optimized());
1565 :
1566 2654198 : JSFunction opt_function = function();
1567 2654198 : Code code = opt_function->code();
1568 :
1569 : // The code object may have been replaced by lazy deoptimization. Fall
1570 : // back to a slow search in this case to find the original optimized
1571 : // code object.
1572 2654198 : if (!code->contains(pc())) {
1573 158764 : code = isolate()->heap()->GcSafeFindCodeForInnerPointer(pc());
1574 : }
1575 : DCHECK(!code.is_null());
1576 : DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
1577 :
1578 2654198 : SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1579 2654198 : if (safepoint_entry.has_deoptimization_index()) {
1580 2654198 : *deopt_index = safepoint_entry.deoptimization_index();
1581 : return DeoptimizationData::cast(code->deoptimization_data());
1582 : }
1583 0 : *deopt_index = Safepoint::kNoDeoptimizationIndex;
1584 0 : return DeoptimizationData();
1585 : }
1586 :
1587 213857 : Object OptimizedFrame::receiver() const {
1588 : Code code = LookupCode();
1589 213857 : if (code->kind() == Code::BUILTIN) {
1590 213850 : Address argc_ptr = fp() + OptimizedBuiltinFrameConstants::kArgCOffset;
1591 213850 : intptr_t argc = *reinterpret_cast<intptr_t*>(argc_ptr);
1592 : intptr_t args_size =
1593 213850 : (StandardFrameConstants::kFixedSlotCountAboveFp + argc) *
1594 213850 : kSystemPointerSize;
1595 213850 : Address receiver_ptr = fp() + args_size;
1596 : return *FullObjectSlot(receiver_ptr);
1597 : } else {
1598 7 : return JavaScriptFrame::receiver();
1599 : }
1600 : }
1601 :
1602 57654 : void OptimizedFrame::GetFunctions(
1603 : std::vector<SharedFunctionInfo>* functions) const {
1604 : DCHECK(functions->empty());
1605 : DCHECK(is_optimized());
1606 :
1607 : // Delegate to JS frame in absence of turbofan deoptimization.
1608 : // TODO(turbofan): Revisit once we support deoptimization across the board.
1609 : Code code = LookupCode();
1610 57654 : if (code->kind() == Code::BUILTIN) {
1611 14588 : return JavaScriptFrame::GetFunctions(functions);
1612 : }
1613 :
1614 : DisallowHeapAllocation no_gc;
1615 43066 : int deopt_index = Safepoint::kNoDeoptimizationIndex;
1616 43066 : DeoptimizationData const data = GetDeoptimizationData(&deopt_index);
1617 : DCHECK(!data.is_null());
1618 : DCHECK_NE(Safepoint::kNoDeoptimizationIndex, deopt_index);
1619 : FixedArray const literal_array = data->LiteralArray();
1620 :
1621 : TranslationIterator it(data->TranslationByteArray(),
1622 86132 : data->TranslationIndex(deopt_index)->value());
1623 43066 : Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
1624 : DCHECK_EQ(Translation::BEGIN, opcode);
1625 43066 : it.Next(); // Skip frame count.
1626 43066 : int jsframe_count = it.Next();
1627 43066 : it.Next(); // Skip update feedback count.
1628 :
1629 : // We insert the frames in reverse order because the frames
1630 : // in the deoptimization translation are ordered bottom-to-top.
1631 225084 : while (jsframe_count != 0) {
1632 182018 : opcode = static_cast<Translation::Opcode>(it.Next());
1633 364036 : if (opcode == Translation::INTERPRETED_FRAME ||
1634 310681 : opcode == Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_FRAME ||
1635 : opcode ==
1636 : Translation::JAVA_SCRIPT_BUILTIN_CONTINUATION_WITH_CATCH_FRAME) {
1637 53355 : it.Next(); // Skip bailout id.
1638 53355 : jsframe_count--;
1639 :
1640 : // The second operand of the frame points to the function.
1641 53355 : Object shared = literal_array->get(it.Next());
1642 106710 : functions->push_back(SharedFunctionInfo::cast(shared));
1643 :
1644 : // Skip over remaining operands to advance to the next opcode.
1645 53355 : it.Skip(Translation::NumberOfOperandsFor(opcode) - 2);
1646 : } else {
1647 : // Skip over operands to advance to the next opcode.
1648 128663 : it.Skip(Translation::NumberOfOperandsFor(opcode));
1649 : }
1650 : }
1651 : }
1652 :
1653 8189249 : int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) {
1654 8189249 : return StandardFrameConstants::kCallerSPOffset -
1655 8189249 : ((slot_index + 1) * kSystemPointerSize);
1656 : }
1657 :
1658 0 : Object OptimizedFrame::StackSlotAt(int index) const {
1659 0 : return Object(Memory<Address>(fp() + StackSlotOffsetRelativeToFp(index)));
1660 : }
1661 :
1662 3348 : int InterpretedFrame::position() const {
1663 3348 : AbstractCode code = AbstractCode::cast(GetBytecodeArray());
1664 : int code_offset = GetBytecodeOffset();
1665 3348 : return code->SourcePosition(code_offset);
1666 : }
1667 :
1668 13718769 : int InterpretedFrame::LookupExceptionHandlerInTable(
1669 : int* context_register, HandlerTable::CatchPrediction* prediction) {
1670 13718769 : HandlerTable table(GetBytecodeArray());
1671 13718769 : return table.LookupRange(GetBytecodeOffset(), context_register, prediction);
1672 : }
1673 :
1674 84354 : int InterpretedFrame::GetBytecodeOffset() const {
1675 : const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1676 : DCHECK_EQ(InterpreterFrameConstants::kBytecodeOffsetFromFp,
1677 : InterpreterFrameConstants::kExpressionsOffset -
1678 : index * kSystemPointerSize);
1679 84354 : int raw_offset = Smi::ToInt(GetExpression(index));
1680 19740618 : return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
1681 : }
1682 :
1683 0 : int InterpretedFrame::GetBytecodeOffset(Address fp) {
1684 : const int offset = InterpreterFrameConstants::kExpressionsOffset;
1685 : const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1686 : DCHECK_EQ(InterpreterFrameConstants::kBytecodeOffsetFromFp,
1687 : InterpreterFrameConstants::kExpressionsOffset -
1688 : index * kSystemPointerSize);
1689 0 : Address expression_offset = fp + offset - index * kSystemPointerSize;
1690 0 : int raw_offset = Smi::ToInt(Object(Memory<Address>(expression_offset)));
1691 0 : return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
1692 : }
1693 :
1694 818999 : void InterpretedFrame::PatchBytecodeOffset(int new_offset) {
1695 : const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1696 : DCHECK_EQ(InterpreterFrameConstants::kBytecodeOffsetFromFp,
1697 : InterpreterFrameConstants::kExpressionsOffset -
1698 : index * kSystemPointerSize);
1699 818999 : int raw_offset = new_offset + BytecodeArray::kHeaderSize - kHeapObjectTag;
1700 818999 : SetExpression(index, Smi::FromInt(raw_offset));
1701 818999 : }
1702 :
1703 13529905 : BytecodeArray InterpretedFrame::GetBytecodeArray() const {
1704 : const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1705 : DCHECK_EQ(InterpreterFrameConstants::kBytecodeArrayFromFp,
1706 : InterpreterFrameConstants::kExpressionsOffset -
1707 : index * kSystemPointerSize);
1708 46716074 : return BytecodeArray::cast(GetExpression(index));
1709 : }
1710 :
1711 8896 : void InterpretedFrame::PatchBytecodeArray(BytecodeArray bytecode_array) {
1712 : const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1713 : DCHECK_EQ(InterpreterFrameConstants::kBytecodeArrayFromFp,
1714 : InterpreterFrameConstants::kExpressionsOffset -
1715 : index * kSystemPointerSize);
1716 8896 : SetExpression(index, bytecode_array);
1717 8896 : }
1718 :
1719 821608 : Object InterpretedFrame::ReadInterpreterRegister(int register_index) const {
1720 : const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1721 : DCHECK_EQ(InterpreterFrameConstants::kRegisterFileFromFp,
1722 : InterpreterFrameConstants::kExpressionsOffset -
1723 : index * kSystemPointerSize);
1724 1643216 : return GetExpression(index + register_index);
1725 : }
1726 :
1727 0 : void InterpretedFrame::WriteInterpreterRegister(int register_index,
1728 : Object value) {
1729 : const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1730 : DCHECK_EQ(InterpreterFrameConstants::kRegisterFileFromFp,
1731 : InterpreterFrameConstants::kExpressionsOffset -
1732 : index * kSystemPointerSize);
1733 0 : return SetExpression(index + register_index, value);
1734 : }
1735 :
1736 5934097 : void InterpretedFrame::Summarize(std::vector<FrameSummary>* functions) const {
1737 : DCHECK(functions->empty());
1738 5934097 : AbstractCode abstract_code = AbstractCode::cast(GetBytecodeArray());
1739 5934097 : Handle<FixedArray> params = GetParameters();
1740 : FrameSummary::JavaScriptFrameSummary summary(
1741 11868194 : isolate(), receiver(), function(), abstract_code, GetBytecodeOffset(),
1742 17802291 : IsConstructor(), *params);
1743 5934097 : functions->push_back(summary);
1744 5934097 : }
1745 :
1746 1587427 : int ArgumentsAdaptorFrame::ComputeParametersCount() const {
1747 3174854 : return Smi::ToInt(GetExpression(0));
1748 : }
1749 :
1750 0 : Code ArgumentsAdaptorFrame::unchecked_code() const {
1751 : return isolate()->builtins()->builtin(
1752 0 : Builtins::kArgumentsAdaptorTrampoline);
1753 : }
1754 :
1755 0 : int BuiltinFrame::ComputeParametersCount() const {
1756 0 : return Smi::ToInt(GetExpression(0));
1757 : }
1758 :
1759 0 : void BuiltinFrame::PrintFrameKind(StringStream* accumulator) const {
1760 0 : accumulator->Add("builtin frame: ");
1761 0 : }
1762 :
1763 2506748 : Address InternalFrame::GetCallerStackPointer() const {
1764 : // Internal frames have no arguments. The stack pointer of the
1765 : // caller is at a fixed offset from the frame pointer.
1766 2506748 : return fp() + StandardFrameConstants::kCallerSPOffset;
1767 : }
1768 :
1769 0 : Code InternalFrame::unchecked_code() const { UNREACHABLE(); }
1770 :
1771 16 : void WasmCompiledFrame::Print(StringStream* accumulator, PrintMode mode,
1772 : int index) const {
1773 : PrintIndex(accumulator, mode, index);
1774 16 : accumulator->Add("WASM [");
1775 32 : accumulator->PrintName(script()->name());
1776 : Address instruction_start = isolate()
1777 : ->wasm_engine()
1778 : ->code_manager()
1779 : ->LookupCode(pc())
1780 16 : ->instruction_start();
1781 : Vector<const uint8_t> raw_func_name =
1782 32 : module_object()->GetRawFunctionName(function_index());
1783 16 : const int kMaxPrintedFunctionName = 64;
1784 : char func_name[kMaxPrintedFunctionName + 1];
1785 32 : int func_name_len = std::min(kMaxPrintedFunctionName, raw_func_name.length());
1786 16 : memcpy(func_name, raw_func_name.start(), func_name_len);
1787 16 : func_name[func_name_len] = '\0';
1788 16 : int pos = position();
1789 32 : const wasm::WasmModule* module = wasm_instance()->module_object()->module();
1790 16 : int func_index = function_index();
1791 32 : int func_code_offset = module->functions[func_index].code.offset();
1792 32 : accumulator->Add("], function #%u ('%s'), pc=%p (+0x%x), pos=%d (+%d)\n",
1793 : func_index, func_name, reinterpret_cast<void*>(pc()),
1794 : static_cast<int>(pc() - instruction_start), pos,
1795 16 : pos - func_code_offset);
1796 16 : if (mode != OVERVIEW) accumulator->Add("\n");
1797 16 : }
1798 :
1799 0 : Code WasmCompiledFrame::unchecked_code() const {
1800 0 : return isolate()->FindCodeObject(pc());
1801 : }
1802 :
1803 5999 : void WasmCompiledFrame::Iterate(RootVisitor* v) const {
1804 5999 : IterateCompiledFrame(v);
1805 5999 : }
1806 :
1807 2626429 : Address WasmCompiledFrame::GetCallerStackPointer() const {
1808 2626429 : return fp() + ExitFrameConstants::kCallerSPOffset;
1809 : }
1810 :
1811 72 : wasm::WasmCode* WasmCompiledFrame::wasm_code() const {
1812 305582 : return isolate()->wasm_engine()->code_manager()->LookupCode(pc());
1813 : }
1814 :
1815 4440 : WasmInstanceObject WasmCompiledFrame::wasm_instance() const {
1816 : const int offset = WasmCompiledFrameConstants::kWasmInstanceOffset;
1817 619996 : Object instance(Memory<Address>(fp() + offset));
1818 4440 : return WasmInstanceObject::cast(instance);
1819 : }
1820 :
1821 0 : WasmModuleObject WasmCompiledFrame::module_object() const {
1822 0 : return wasm_instance()->module_object();
1823 : }
1824 :
1825 104 : uint32_t WasmCompiledFrame::function_index() const {
1826 208 : return FrameSummary::GetSingle(this).AsWasmCompiled().function_index();
1827 : }
1828 :
1829 32 : Script WasmCompiledFrame::script() const { return module_object()->script(); }
1830 :
1831 88 : int WasmCompiledFrame::position() const {
1832 176 : return FrameSummary::GetSingle(this).SourcePosition();
1833 : }
1834 :
1835 305510 : void WasmCompiledFrame::Summarize(std::vector<FrameSummary>* functions) const {
1836 : DCHECK(functions->empty());
1837 : wasm::WasmCode* code = wasm_code();
1838 611020 : int offset = static_cast<int>(pc() - code->instruction_start());
1839 : Handle<WasmInstanceObject> instance(wasm_instance(), isolate());
1840 : FrameSummary::WasmCompiledFrameSummary summary(
1841 305510 : isolate(), instance, code, offset, at_to_number_conversion());
1842 305510 : functions->push_back(summary);
1843 305510 : }
1844 :
1845 305510 : bool WasmCompiledFrame::at_to_number_conversion() const {
1846 : // Check whether our callee is a WASM_TO_JS frame, and this frame is at the
1847 : // ToNumber conversion call.
1848 : wasm::WasmCode* code =
1849 : callee_pc() != kNullAddress
1850 : ? isolate()->wasm_engine()->code_manager()->LookupCode(callee_pc())
1851 310038 : : nullptr;
1852 305510 : if (!code || code->kind() != wasm::WasmCode::kWasmToJsWrapper) return false;
1853 1032 : int offset = static_cast<int>(callee_pc() - code->instruction_start());
1854 : int pos = FrameSummary::WasmCompiledFrameSummary::GetWasmSourcePosition(
1855 516 : code, offset);
1856 : DCHECK(pos == 0 || pos == 1);
1857 : // The imported call has position 0, ToNumber has position 1.
1858 516 : return !!pos;
1859 : }
1860 :
1861 2464803 : int WasmCompiledFrame::LookupExceptionHandlerInTable(int* stack_slots) {
1862 : DCHECK_NOT_NULL(stack_slots);
1863 : wasm::WasmCode* code =
1864 2464803 : isolate()->wasm_engine()->code_manager()->LookupCode(pc());
1865 2464803 : if (!code->IsAnonymous() && code->handler_table_offset() > 0) {
1866 792 : HandlerTable table(code->instruction_start(), code->handler_table_offset());
1867 1584 : int pc_offset = static_cast<int>(pc() - code->instruction_start());
1868 792 : *stack_slots = static_cast<int>(code->stack_slots());
1869 792 : return table.LookupReturn(pc_offset);
1870 : }
1871 : return -1;
1872 : }
1873 :
1874 19 : void WasmInterpreterEntryFrame::Iterate(RootVisitor* v) const {
1875 19 : IterateCompiledFrame(v);
1876 19 : }
1877 :
1878 0 : void WasmInterpreterEntryFrame::Print(StringStream* accumulator, PrintMode mode,
1879 : int index) const {
1880 : PrintIndex(accumulator, mode, index);
1881 0 : accumulator->Add("WASM INTERPRETER ENTRY [");
1882 0 : Script script = this->script();
1883 0 : accumulator->PrintName(script->name());
1884 0 : accumulator->Add("]");
1885 0 : if (mode != OVERVIEW) accumulator->Add("\n");
1886 0 : }
1887 :
1888 3916 : void WasmInterpreterEntryFrame::Summarize(
1889 : std::vector<FrameSummary>* functions) const {
1890 : Handle<WasmInstanceObject> instance(wasm_instance(), isolate());
1891 : std::vector<std::pair<uint32_t, int>> interpreted_stack =
1892 3916 : instance->debug_info()->GetInterpretedStack(fp());
1893 :
1894 680400 : for (auto& e : interpreted_stack) {
1895 : FrameSummary::WasmInterpretedFrameSummary summary(isolate(), instance,
1896 676484 : e.first, e.second);
1897 676484 : functions->push_back(summary);
1898 : }
1899 3916 : }
1900 :
1901 0 : Code WasmInterpreterEntryFrame::unchecked_code() const { UNREACHABLE(); }
1902 :
1903 34929 : WasmInstanceObject WasmInterpreterEntryFrame::wasm_instance() const {
1904 : const int offset = WasmCompiledFrameConstants::kWasmInstanceOffset;
1905 82666 : Object instance(Memory<Address>(fp() + offset));
1906 34929 : return WasmInstanceObject::cast(instance);
1907 : }
1908 :
1909 2028 : WasmDebugInfo WasmInterpreterEntryFrame::debug_info() const {
1910 2028 : return wasm_instance()->debug_info();
1911 : }
1912 :
1913 0 : WasmModuleObject WasmInterpreterEntryFrame::module_object() const {
1914 0 : return wasm_instance()->module_object();
1915 : }
1916 :
1917 0 : Script WasmInterpreterEntryFrame::script() const {
1918 0 : return module_object()->script();
1919 : }
1920 :
1921 0 : int WasmInterpreterEntryFrame::position() const {
1922 0 : return FrameSummary::GetBottom(this).AsWasmInterpreted().SourcePosition();
1923 : }
1924 :
1925 460 : Object WasmInterpreterEntryFrame::context() const {
1926 460 : return wasm_instance()->native_context();
1927 : }
1928 :
1929 5737 : Address WasmInterpreterEntryFrame::GetCallerStackPointer() const {
1930 5737 : return fp() + ExitFrameConstants::kCallerSPOffset;
1931 : }
1932 :
1933 0 : Code WasmCompileLazyFrame::unchecked_code() const { return Code(); }
1934 :
1935 0 : WasmInstanceObject WasmCompileLazyFrame::wasm_instance() const {
1936 0 : return WasmInstanceObject::cast(*wasm_instance_slot());
1937 : }
1938 :
1939 0 : FullObjectSlot WasmCompileLazyFrame::wasm_instance_slot() const {
1940 : const int offset = WasmCompileLazyFrameConstants::kWasmInstanceOffset;
1941 0 : return FullObjectSlot(&Memory<Address>(fp() + offset));
1942 : }
1943 :
1944 0 : void WasmCompileLazyFrame::Iterate(RootVisitor* v) const {
1945 : const int header_size = WasmCompileLazyFrameConstants::kFixedFrameSizeFromFp;
1946 : FullObjectSlot base(&Memory<Address>(sp()));
1947 0 : FullObjectSlot limit(&Memory<Address>(fp() - header_size));
1948 0 : v->VisitRootPointers(Root::kTop, nullptr, base, limit);
1949 0 : v->VisitRootPointer(Root::kTop, nullptr, wasm_instance_slot());
1950 0 : }
1951 :
1952 0 : Address WasmCompileLazyFrame::GetCallerStackPointer() const {
1953 0 : return fp() + WasmCompileLazyFrameConstants::kCallerSPOffset;
1954 : }
1955 :
1956 : namespace {
1957 :
1958 24 : void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo shared,
1959 : Code code) {
1960 48 : if (FLAG_max_stack_trace_source_length != 0 && !code.is_null()) {
1961 48 : std::ostringstream os;
1962 : os << "--------- s o u r c e c o d e ---------\n"
1963 72 : << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1964 24 : << "\n-----------------------------------------\n";
1965 48 : accumulator->Add(os.str().c_str());
1966 : }
1967 24 : }
1968 :
1969 : } // namespace
1970 :
1971 :
1972 57 : void JavaScriptFrame::Print(StringStream* accumulator,
1973 : PrintMode mode,
1974 : int index) const {
1975 : DisallowHeapAllocation no_gc;
1976 57 : Object receiver = this->receiver();
1977 57 : JSFunction function = this->function();
1978 :
1979 57 : accumulator->PrintSecurityTokenIfChanged(function);
1980 : PrintIndex(accumulator, mode, index);
1981 57 : PrintFrameKind(accumulator);
1982 57 : Code code;
1983 57 : if (IsConstructor()) accumulator->Add("new ");
1984 57 : accumulator->PrintFunction(function, receiver, &code);
1985 57 : accumulator->Add(" [%p]", function);
1986 :
1987 : // Get scope information for nicer output, if possible. If code is nullptr, or
1988 : // doesn't contain scope info, scope_info will return 0 for the number of
1989 : // parameters, stack local variables, context local variables, stack slots,
1990 : // or context slots.
1991 57 : SharedFunctionInfo shared = function->shared();
1992 57 : ScopeInfo scope_info = shared->scope_info();
1993 57 : Object script_obj = shared->script();
1994 57 : if (script_obj->IsScript()) {
1995 57 : Script script = Script::cast(script_obj);
1996 57 : accumulator->Add(" [");
1997 57 : accumulator->PrintName(script->name());
1998 :
1999 114 : if (is_interpreted()) {
2000 : const InterpretedFrame* iframe =
2001 : reinterpret_cast<const InterpretedFrame*>(this);
2002 : BytecodeArray bytecodes = iframe->GetBytecodeArray();
2003 : int offset = iframe->GetBytecodeOffset();
2004 50 : int source_pos = AbstractCode::cast(bytecodes)->SourcePosition(offset);
2005 50 : int line = script->GetLineNumber(source_pos) + 1;
2006 50 : accumulator->Add(":%d] [bytecode=%p offset=%d]", line,
2007 50 : reinterpret_cast<void*>(bytecodes.ptr()), offset);
2008 : } else {
2009 7 : int function_start_pos = shared->StartPosition();
2010 7 : int line = script->GetLineNumber(function_start_pos) + 1;
2011 7 : accumulator->Add(":~%d] [pc=%p]", line, reinterpret_cast<void*>(pc()));
2012 : }
2013 : }
2014 :
2015 57 : accumulator->Add("(this=%o", receiver);
2016 :
2017 : // Print the parameters.
2018 57 : int parameters_count = ComputeParametersCount();
2019 57 : for (int i = 0; i < parameters_count; i++) {
2020 0 : accumulator->Add(",");
2021 0 : accumulator->Add("%o", GetParameter(i));
2022 : }
2023 :
2024 57 : accumulator->Add(")");
2025 57 : if (mode == OVERVIEW) {
2026 33 : accumulator->Add("\n");
2027 33 : return;
2028 : }
2029 48 : if (is_optimized()) {
2030 3 : accumulator->Add(" {\n// optimized frame\n");
2031 3 : PrintFunctionSource(accumulator, shared, code);
2032 3 : accumulator->Add("}\n");
2033 3 : return;
2034 : }
2035 21 : accumulator->Add(" {\n");
2036 :
2037 : // Compute the number of locals and expression stack elements.
2038 21 : int heap_locals_count = scope_info->ContextLocalCount();
2039 21 : int expressions_count = ComputeExpressionsCount();
2040 :
2041 : // Try to get hold of the context of this frame.
2042 21 : Context context;
2043 42 : if (this->context()->IsContext()) {
2044 21 : context = Context::cast(this->context());
2045 21 : while (context->IsWithContext()) {
2046 0 : context = context->previous();
2047 : DCHECK(!context.is_null());
2048 : }
2049 : }
2050 :
2051 : // Print heap-allocated local variables.
2052 21 : if (heap_locals_count > 0) {
2053 0 : accumulator->Add(" // heap-allocated locals\n");
2054 : }
2055 21 : for (int i = 0; i < heap_locals_count; i++) {
2056 0 : accumulator->Add(" var ");
2057 0 : accumulator->PrintName(scope_info->ContextLocalName(i));
2058 0 : accumulator->Add(" = ");
2059 0 : if (!context.is_null()) {
2060 0 : int index = Context::MIN_CONTEXT_SLOTS + i;
2061 0 : if (index < context->length()) {
2062 0 : accumulator->Add("%o", context->get(index));
2063 : } else {
2064 : accumulator->Add(
2065 0 : "// warning: missing context slot - inconsistent frame?");
2066 : }
2067 : } else {
2068 0 : accumulator->Add("// warning: no context found - inconsistent frame?");
2069 : }
2070 0 : accumulator->Add("\n");
2071 : }
2072 :
2073 : // Print the expression stack.
2074 21 : if (0 < expressions_count) {
2075 14 : accumulator->Add(" // expression stack (top to bottom)\n");
2076 : }
2077 147 : for (int i = expressions_count - 1; i >= 0; i--) {
2078 126 : accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
2079 : }
2080 :
2081 21 : PrintFunctionSource(accumulator, shared, code);
2082 :
2083 21 : accumulator->Add("}\n\n");
2084 : }
2085 :
2086 :
2087 32 : void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
2088 : PrintMode mode,
2089 : int index) const {
2090 32 : int actual = ComputeParametersCount();
2091 : int expected = -1;
2092 32 : JSFunction function = this->function();
2093 32 : expected = function->shared()->internal_formal_parameter_count();
2094 :
2095 : PrintIndex(accumulator, mode, index);
2096 32 : accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
2097 32 : if (mode == OVERVIEW) {
2098 16 : accumulator->Add("\n");
2099 16 : return;
2100 : }
2101 16 : accumulator->Add(" {\n");
2102 :
2103 : // Print actual arguments.
2104 16 : if (actual > 0) accumulator->Add(" // actual arguments\n");
2105 48 : for (int i = 0; i < actual; i++) {
2106 16 : accumulator->Add(" [%02d] : %o", i, GetParameter(i));
2107 16 : if (expected != -1 && i >= expected) {
2108 16 : accumulator->Add(" // not passed to callee");
2109 : }
2110 16 : accumulator->Add("\n");
2111 : }
2112 :
2113 16 : accumulator->Add("}\n\n");
2114 : }
2115 :
2116 155174 : void EntryFrame::Iterate(RootVisitor* v) const {
2117 155174 : IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
2118 155174 : }
2119 :
2120 0 : void StandardFrame::IterateExpressions(RootVisitor* v) const {
2121 : const int offset = StandardFrameConstants::kLastObjectOffset;
2122 : FullObjectSlot base(&Memory<Address>(sp()));
2123 4341708 : FullObjectSlot limit(&Memory<Address>(fp() + offset) + 1);
2124 2170854 : v->VisitRootPointers(Root::kTop, nullptr, base, limit);
2125 0 : }
2126 :
2127 1977983 : void JavaScriptFrame::Iterate(RootVisitor* v) const {
2128 : IterateExpressions(v);
2129 1977983 : IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
2130 1977983 : }
2131 :
2132 192871 : void InternalFrame::Iterate(RootVisitor* v) const {
2133 : Code code = LookupCode();
2134 192871 : IteratePc(v, pc_address(), constant_pool_address(), code);
2135 : // Internal frames typically do not receive any arguments, hence their stack
2136 : // only contains tagged pointers.
2137 : // We are misusing the has_tagged_params flag here to tell us whether
2138 : // the full stack frame contains only tagged pointers or only raw values.
2139 : // This is used for the WasmCompileLazy builtin, where we actually pass
2140 : // untagged arguments and also store untagged values on the stack.
2141 192871 : if (code->has_tagged_params()) IterateExpressions(v);
2142 192871 : }
2143 :
2144 : // -------------------------------------------------------------------------
2145 :
2146 : namespace {
2147 :
2148 55944643 : uint32_t PcAddressForHashing(Isolate* isolate, Address address) {
2149 55944643 : if (InstructionStream::PcIsOffHeap(isolate, address)) {
2150 : // Ensure that we get predictable hashes for addresses in embedded code.
2151 : return EmbeddedData::FromBlob(isolate).AddressForHashing(address);
2152 : }
2153 10419788 : return ObjectAddressForHashing(address);
2154 : }
2155 :
2156 : } // namespace
2157 :
2158 : InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
2159 55944649 : InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
2160 111889298 : isolate_->counters()->pc_to_code()->Increment();
2161 : DCHECK(base::bits::IsPowerOfTwo(kInnerPointerToCodeCacheSize));
2162 : uint32_t hash =
2163 55944645 : ComputeUnseededHash(PcAddressForHashing(isolate_, inner_pointer));
2164 55944574 : uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
2165 55944574 : InnerPointerToCodeCacheEntry* entry = cache(index);
2166 55944574 : if (entry->inner_pointer == inner_pointer) {
2167 110069514 : isolate_->counters()->pc_to_code_cached()->Increment();
2168 : DCHECK(entry->code ==
2169 : isolate_->heap()->GcSafeFindCodeForInnerPointer(inner_pointer));
2170 : } else {
2171 : // Because this code may be interrupted by a profiling signal that
2172 : // also queries the cache, we cannot update inner_pointer before the code
2173 : // has been set. Otherwise, we risk trying to use a cache entry before
2174 : // the code has been computed.
2175 : entry->code =
2176 1819634 : isolate_->heap()->GcSafeFindCodeForInnerPointer(inner_pointer);
2177 909817 : entry->safepoint_entry.Reset();
2178 909817 : entry->inner_pointer = inner_pointer;
2179 : }
2180 55944576 : return entry;
2181 : }
2182 : } // namespace internal
2183 120216 : } // namespace v8
|