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/full-codegen/full-codegen.h"
14 : #include "src/ic/ic-stats.h"
15 : #include "src/register-configuration.h"
16 : #include "src/safepoint-table.h"
17 : #include "src/string-stream.h"
18 : #include "src/visitors.h"
19 : #include "src/vm-state-inl.h"
20 : #include "src/wasm/wasm-module.h"
21 : #include "src/wasm/wasm-objects.h"
22 :
23 : namespace v8 {
24 : namespace internal {
25 :
26 : ReturnAddressLocationResolver
27 : StackFrame::return_address_location_resolver_ = NULL;
28 :
29 :
30 : // Iterator that supports traversing the stack handlers of a
31 : // particular frame. Needs to know the top of the handler chain.
32 : class StackHandlerIterator BASE_EMBEDDED {
33 : public:
34 92029163 : StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
35 : : limit_(frame->fp()), handler_(handler) {
36 : // Make sure the handler has already been unwound to this frame.
37 : DCHECK(frame->sp() <= handler->address());
38 : }
39 :
40 : StackHandler* handler() const { return handler_; }
41 :
42 : bool done() {
43 95144938 : return handler_ == NULL || handler_->address() > limit_;
44 : }
45 : void Advance() {
46 : DCHECK(!done());
47 : handler_ = handler_->next();
48 : }
49 :
50 : private:
51 : const Address limit_;
52 : StackHandler* handler_;
53 : };
54 :
55 :
56 : // -------------------------------------------------------------------------
57 :
58 :
59 : #define INITIALIZE_SINGLETON(type, field) field##_(this),
60 19501262 : StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
61 : bool can_access_heap_objects)
62 : : isolate_(isolate),
63 : STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
64 : frame_(NULL), handler_(NULL),
65 39002524 : can_access_heap_objects_(can_access_heap_objects) {
66 19501262 : }
67 : #undef INITIALIZE_SINGLETON
68 :
69 18849709 : StackFrameIterator::StackFrameIterator(Isolate* isolate)
70 37699421 : : StackFrameIterator(isolate, isolate->thread_local_top()) {}
71 :
72 416500 : StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
73 19266209 : : StackFrameIteratorBase(isolate, true) {
74 19266212 : Reset(t);
75 416499 : }
76 :
77 92029164 : void StackFrameIterator::Advance() {
78 : DCHECK(!done());
79 : // Compute the state of the calling frame before restoring
80 : // callee-saved registers and unwinding handlers. This allows the
81 : // frame code that computes the caller state to access the top
82 : // handler and the value of any callee-saved register if needed.
83 92029164 : StackFrame::State state;
84 92029164 : StackFrame::Type type = frame_->GetCallerState(&state);
85 :
86 : // Unwind handlers corresponding to the current frame.
87 92029163 : StackHandlerIterator it(frame_, handler_);
88 95144938 : while (!it.done()) it.Advance();
89 92029163 : handler_ = it.handler();
90 :
91 : // Advance to the calling frame.
92 92029163 : frame_ = SingletonFor(type, &state);
93 :
94 : // When we're done iterating over the stack frames, the handler
95 : // chain must have been completely unwound.
96 : DCHECK(!done() || handler_ == NULL);
97 92029159 : }
98 :
99 :
100 57798636 : void StackFrameIterator::Reset(ThreadLocalTop* top) {
101 19266212 : StackFrame::State state;
102 : StackFrame::Type type = ExitFrame::GetStateForFramePointer(
103 19266212 : Isolate::c_entry_fp(top), &state);
104 19266212 : handler_ = StackHandler::FromAddress(Isolate::handler(top));
105 19266212 : frame_ = SingletonFor(type, &state);
106 19266212 : }
107 :
108 :
109 112437067 : StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
110 : StackFrame::State* state) {
111 112437067 : StackFrame* result = SingletonFor(type);
112 : DCHECK((!result) == (type == StackFrame::NONE));
113 112437061 : if (result) result->state_ = *state;
114 112437061 : return result;
115 : }
116 :
117 :
118 113346020 : StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
119 : #define FRAME_TYPE_CASE(type, field) \
120 : case StackFrame::type: \
121 : return &field##_;
122 :
123 113346020 : switch (type) {
124 : case StackFrame::NONE: return NULL;
125 3674295 : STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
126 : default: break;
127 : }
128 : return NULL;
129 :
130 : #undef FRAME_TYPE_CASE
131 : }
132 :
133 : // -------------------------------------------------------------------------
134 :
135 4287948 : void JavaScriptFrameIterator::Advance() {
136 7630474 : do {
137 7630474 : iterator_.Advance();
138 7630474 : } while (!iterator_.done() && !iterator_.frame()->is_java_script());
139 4287948 : }
140 :
141 :
142 84294 : void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
143 168588 : if (!frame()->has_adapted_arguments()) return;
144 4663 : iterator_.Advance();
145 : DCHECK(iterator_.frame()->is_arguments_adaptor());
146 : }
147 :
148 :
149 : // -------------------------------------------------------------------------
150 :
151 3068091 : StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
152 3068091 : : iterator_(isolate) {
153 3068091 : if (!done() && !IsValidFrame(iterator_.frame())) Advance();
154 3068091 : }
155 :
156 990477 : StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate,
157 : StackFrame::Id id)
158 990477 : : StackTraceFrameIterator(isolate) {
159 6697415 : while (!done() && frame()->id() != id) Advance();
160 990477 : }
161 :
162 11886311 : void StackTraceFrameIterator::Advance() {
163 30544443 : do {
164 30544443 : iterator_.Advance();
165 30544443 : } while (!done() && !IsValidFrame(iterator_.frame()));
166 11886311 : }
167 :
168 32918329 : bool StackTraceFrameIterator::IsValidFrame(StackFrame* frame) const {
169 32918329 : if (frame->is_java_script()) {
170 : JavaScriptFrame* jsFrame = static_cast<JavaScriptFrame*>(frame);
171 28652330 : if (!jsFrame->function()->IsJSFunction()) return false;
172 28652330 : return jsFrame->function()->shared()->IsSubjectToDebugging();
173 : }
174 : // apart from javascript, only wasm is valid
175 18592164 : return frame->is_wasm();
176 : }
177 :
178 16015 : void StackTraceFrameIterator::AdvanceToArgumentsFrame() {
179 48045 : if (!is_javascript() || !javascript_frame()->has_adapted_arguments()) return;
180 16015 : iterator_.Advance();
181 : DCHECK(iterator_.frame()->is_arguments_adaptor());
182 : }
183 :
184 : // -------------------------------------------------------------------------
185 :
186 : namespace {
187 :
188 554563 : bool IsInterpreterFramePc(Isolate* isolate, Address pc) {
189 : Code* interpreter_entry_trampoline =
190 : isolate->builtins()->builtin(Builtins::kInterpreterEntryTrampoline);
191 : Code* interpreter_bytecode_advance =
192 : isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeAdvance);
193 : Code* interpreter_bytecode_dispatch =
194 : isolate->builtins()->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
195 :
196 1093906 : return (pc >= interpreter_entry_trampoline->instruction_start() &&
197 192761 : pc < interpreter_entry_trampoline->instruction_end()) ||
198 370302 : (pc >= interpreter_bytecode_advance->instruction_start() &&
199 747324 : pc < interpreter_bytecode_advance->instruction_end()) ||
200 370302 : (pc >= interpreter_bytecode_dispatch->instruction_start() &&
201 554563 : pc < interpreter_bytecode_dispatch->instruction_end());
202 : }
203 :
204 : DISABLE_ASAN Address ReadMemoryAt(Address address) {
205 24487 : return Memory::Address_at(address);
206 : }
207 :
208 : } // namespace
209 :
210 235053 : SafeStackFrameIterator::SafeStackFrameIterator(
211 235053 : Isolate* isolate,
212 51273 : Address fp, Address sp, Address js_entry_sp)
213 : : StackFrameIteratorBase(isolate, false),
214 : low_bound_(sp),
215 : high_bound_(js_entry_sp),
216 : top_frame_type_(StackFrame::NONE),
217 470106 : external_callback_scope_(isolate->external_callback_scope()) {
218 235053 : StackFrame::State state;
219 : StackFrame::Type type;
220 443320 : ThreadLocalTop* top = isolate->thread_local_top();
221 : bool advance_frame = true;
222 235053 : if (IsValidTop(top)) {
223 208267 : type = ExitFrame::GetStateForFramePointer(Isolate::c_entry_fp(top), &state);
224 208267 : top_frame_type_ = type;
225 26786 : } else if (IsValidStackAddress(fp)) {
226 : DCHECK(fp != NULL);
227 24487 : state.fp = fp;
228 24487 : state.sp = sp;
229 : state.pc_address = StackFrame::ResolveReturnAddressLocation(
230 48974 : reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
231 :
232 : // If the top of stack is a return address to the interpreter trampoline,
233 : // then we are likely in a bytecode handler with elided frame. In that
234 : // case, set the PC properly and make sure we do not drop the frame.
235 24487 : if (IsValidStackAddress(sp)) {
236 : MSAN_MEMORY_IS_INITIALIZED(sp, kPointerSize);
237 : Address tos = ReadMemoryAt(reinterpret_cast<Address>(sp));
238 24487 : if (IsInterpreterFramePc(isolate, tos)) {
239 9786 : state.pc_address = reinterpret_cast<Address*>(sp);
240 : advance_frame = false;
241 : }
242 : }
243 :
244 : // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
245 : // we check only that kMarkerOffset is within the stack bounds and do
246 : // compile time check that kContextOffset slot is pushed on the stack before
247 : // kMarkerOffset.
248 : STATIC_ASSERT(StandardFrameConstants::kFunctionOffset <
249 : StandardFrameConstants::kContextOffset);
250 24487 : Address frame_marker = fp + StandardFrameConstants::kFunctionOffset;
251 24487 : if (IsValidStackAddress(frame_marker)) {
252 23236 : type = StackFrame::ComputeType(this, &state);
253 23236 : top_frame_type_ = type;
254 : // We only keep the top frame if we believe it to be interpreted frame.
255 23236 : if (type != StackFrame::INTERPRETED) {
256 : advance_frame = true;
257 : }
258 : } else {
259 : // Mark the frame as JAVA_SCRIPT if we cannot determine its type.
260 : // The frame anyways will be skipped.
261 : type = StackFrame::JAVA_SCRIPT;
262 : // Top frame is incomplete so we cannot reliably determine its type.
263 1251 : top_frame_type_ = StackFrame::NONE;
264 : }
265 : } else {
266 2299 : return;
267 : }
268 232754 : frame_ = SingletonFor(type, &state);
269 232754 : if (advance_frame && frame_) Advance();
270 : }
271 :
272 :
273 447993 : bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
274 : Address c_entry_fp = Isolate::c_entry_fp(top);
275 235053 : if (!IsValidExitFrame(c_entry_fp)) return false;
276 : // There should be at least one JS_ENTRY stack handler.
277 : Address handler = Isolate::handler(top);
278 212940 : if (handler == NULL) return false;
279 : // Check that there are no js frames on top of the native frames.
280 212940 : return c_entry_fp < handler;
281 : }
282 :
283 :
284 1141700 : void SafeStackFrameIterator::AdvanceOneFrame() {
285 : DCHECK(!done());
286 1141700 : StackFrame* last_frame = frame_;
287 : Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
288 : // Before advancing to the next stack frame, perform pointer validity tests.
289 1141700 : if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
290 232747 : frame_ = NULL;
291 465494 : return;
292 : }
293 :
294 : // Advance to the previous frame.
295 908953 : StackFrame::State state;
296 2726859 : StackFrame::Type type = frame_->GetCallerState(&state);
297 908953 : frame_ = SingletonFor(type, &state);
298 908953 : if (!frame_) return;
299 :
300 : // Check that we have actually moved to the previous frame in the stack.
301 1817906 : if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
302 0 : frame_ = NULL;
303 : }
304 : }
305 :
306 :
307 1141700 : bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
308 2283400 : return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
309 : }
310 :
311 :
312 2288544 : bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
313 1141700 : StackFrame::State state;
314 2045509 : if (frame->is_entry() || frame->is_entry_construct()) {
315 : // See EntryFrame::GetCallerState. It computes the caller FP address
316 : // and calls ExitFrame::GetStateForFramePointer on it. We need to be
317 : // sure that caller FP address is valid.
318 : Address caller_fp = Memory::Address_at(
319 237891 : frame->fp() + EntryFrameConstants::kCallerFPOffset);
320 237891 : if (!IsValidExitFrame(caller_fp)) return false;
321 903809 : } else if (frame->is_arguments_adaptor()) {
322 : // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
323 : // the number of arguments is stored on stack as Smi. We need to check
324 : // that it really an Smi.
325 : Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
326 4425 : GetExpression(0);
327 4425 : if (!number_of_args->IsSmi()) {
328 : return false;
329 : }
330 : }
331 908953 : frame->ComputeCallerState(&state);
332 3635812 : return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
333 1817906 : SingletonFor(frame->GetCallerState(&state)) != NULL;
334 : }
335 :
336 :
337 472944 : bool SafeStackFrameIterator::IsValidExitFrame(Address fp) const {
338 472944 : if (!IsValidStackAddress(fp)) return false;
339 : Address sp = ExitFrame::ComputeStackPointer(fp);
340 218585 : if (!IsValidStackAddress(sp)) return false;
341 : StackFrame::State state;
342 : ExitFrame::FillState(fp, sp, &state);
343 : MSAN_MEMORY_IS_INITIALIZED(state.pc_address, sizeof(state.pc_address));
344 218084 : return *state.pc_address != nullptr;
345 : }
346 :
347 :
348 494399 : void SafeStackFrameIterator::Advance() {
349 : while (true) {
350 1141700 : AdvanceOneFrame();
351 1141700 : if (done()) break;
352 : ExternalCallbackScope* last_callback_scope = NULL;
353 997989 : while (external_callback_scope_ != NULL &&
354 55959 : external_callback_scope_->scope_address() < frame_->fp()) {
355 : // As long as the setup of a frame is not atomic, we may happen to be
356 : // in an interval where an ExternalCallbackScope is already created,
357 : // but the frame is not yet entered. So we are actually observing
358 : // the previous frame.
359 : // Skip all the ExternalCallbackScope's that are below the current fp.
360 : last_callback_scope = external_callback_scope_;
361 33077 : external_callback_scope_ = external_callback_scope_->previous();
362 : }
363 908953 : if (frame_->is_java_script()) break;
364 1952191 : if (frame_->is_exit() || frame_->is_builtin_exit()) {
365 : // Some of the EXIT frames may have ExternalCallbackScope allocated on
366 : // top of them. In that case the scope corresponds to the first EXIT
367 : // frame beneath it. There may be other EXIT frames on top of the
368 : // ExternalCallbackScope, just skip them as we cannot collect any useful
369 : // information about them.
370 5144 : if (last_callback_scope) {
371 : frame_->state_.pc_address =
372 10288 : last_callback_scope->callback_entrypoint_address();
373 : }
374 : break;
375 : }
376 : }
377 494399 : }
378 :
379 :
380 : // -------------------------------------------------------------------------
381 :
382 :
383 1665019 : Code* StackFrame::GetSafepointData(Isolate* isolate,
384 : Address inner_pointer,
385 : SafepointEntry* safepoint_entry,
386 : unsigned* stack_slots) {
387 : InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
388 1665019 : isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
389 1665019 : if (!entry->safepoint_entry.is_valid()) {
390 104304 : entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
391 : DCHECK(entry->safepoint_entry.is_valid());
392 : } else {
393 : DCHECK(entry->safepoint_entry.Equals(
394 : entry->code->GetSafepointEntry(inner_pointer)));
395 : }
396 :
397 : // Fill in the results and return the code.
398 1665019 : Code* code = entry->code;
399 1665019 : *safepoint_entry = entry->safepoint_entry;
400 1665019 : *stack_slots = code->stack_slots();
401 1665019 : return code;
402 : }
403 :
404 :
405 : #ifdef DEBUG
406 : static bool GcSafeCodeContains(HeapObject* object, Address addr);
407 : #endif
408 :
409 0 : void StackFrame::IteratePc(RootVisitor* v, Address* pc_address,
410 : Address* constant_pool_address, Code* holder) {
411 4513003 : Address pc = *pc_address;
412 : DCHECK(GcSafeCodeContains(holder, pc));
413 4513003 : unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
414 4513003 : Object* code = holder;
415 4513003 : v->VisitRootPointer(Root::kTop, &code);
416 9025640 : if (code == holder) return;
417 : holder = reinterpret_cast<Code*>(code);
418 366 : pc = holder->instruction_start() + pc_offset;
419 366 : *pc_address = pc;
420 : if (FLAG_enable_embedded_constant_pool && constant_pool_address) {
421 : *constant_pool_address = holder->constant_pool();
422 : }
423 : }
424 :
425 :
426 0 : void StackFrame::SetReturnAddressLocationResolver(
427 : ReturnAddressLocationResolver resolver) {
428 : DCHECK(return_address_location_resolver_ == NULL);
429 0 : return_address_location_resolver_ = resolver;
430 0 : }
431 :
432 180187704 : StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
433 : State* state) {
434 : DCHECK(state->fp != NULL);
435 :
436 : MSAN_MEMORY_IS_INITIALIZED(
437 : state->fp + CommonFrameConstants::kContextOrFrameTypeOffset,
438 : kPointerSize);
439 : intptr_t marker = Memory::intptr_at(
440 90744241 : state->fp + CommonFrameConstants::kContextOrFrameTypeOffset);
441 90744241 : if (!iterator->can_access_heap_objects_) {
442 : // TODO(titzer): "can_access_heap_objects" is kind of bogus. It really
443 : // means that we are being called from the profiler, which can interrupt
444 : // the VM with a signal at any arbitrary instruction, with essentially
445 : // anything on the stack. So basically none of these checks are 100%
446 : // reliable.
447 : MSAN_MEMORY_IS_INITIALIZED(
448 : state->fp + StandardFrameConstants::kFunctionOffset, kPointerSize);
449 : Object* maybe_function =
450 1830854 : Memory::Object_at(state->fp + StandardFrameConstants::kFunctionOffset);
451 1830854 : if (!StackFrame::IsTypeMarker(marker)) {
452 530076 : if (maybe_function->IsSmi()) {
453 : return NONE;
454 530076 : } else if (IsInterpreterFramePc(iterator->isolate(),
455 530076 : *(state->pc_address))) {
456 : return INTERPRETED;
457 : } else {
458 178060 : return JAVA_SCRIPT;
459 : }
460 : }
461 : } else {
462 : // Look up the code object to figure out the type of the stack frame.
463 : Code* code_obj =
464 88913387 : GetContainingCode(iterator->isolate(), *(state->pc_address));
465 88913387 : if (code_obj != nullptr) {
466 88913386 : switch (code_obj->kind()) {
467 : case Code::BUILTIN:
468 37113721 : if (StackFrame::IsTypeMarker(marker)) break;
469 28793663 : if (code_obj->is_interpreter_trampoline_builtin()) {
470 : return INTERPRETED;
471 : }
472 878144 : if (code_obj->is_turbofanned()) {
473 : // TODO(bmeurer): We treat frames for BUILTIN Code objects as
474 : // OptimizedFrame for now (all the builtins with JavaScript
475 : // linkage are actually generated with TurboFan currently, so
476 : // this is sound).
477 : return OPTIMIZED;
478 : }
479 12947 : return BUILTIN;
480 : case Code::FUNCTION:
481 : return JAVA_SCRIPT;
482 : case Code::OPTIMIZED_FUNCTION:
483 5656051 : return OPTIMIZED;
484 : case Code::WASM_FUNCTION:
485 2538567 : return WASM_COMPILED;
486 : case Code::WASM_TO_JS_FUNCTION:
487 18791 : return WASM_TO_JS;
488 : case Code::JS_TO_WASM_FUNCTION:
489 103551 : return JS_TO_WASM;
490 : case Code::WASM_INTERPRETER_ENTRY:
491 56465 : return WASM_INTERPRETER_ENTRY;
492 : default:
493 : // All other types should have an explicit marker
494 : break;
495 : }
496 : } else {
497 : return NONE;
498 : }
499 : }
500 :
501 : DCHECK(StackFrame::IsTypeMarker(marker));
502 : StackFrame::Type candidate = StackFrame::MarkerToType(marker);
503 40730621 : switch (candidate) {
504 : case ENTRY:
505 : case ENTRY_CONSTRUCT:
506 : case EXIT:
507 : case BUILTIN_EXIT:
508 : case STUB:
509 : case STUB_FAILURE_TRAMPOLINE:
510 : case INTERNAL:
511 : case CONSTRUCT:
512 : case ARGUMENTS_ADAPTOR:
513 : case WASM_TO_JS:
514 : case WASM_COMPILED:
515 : return candidate;
516 : case JS_TO_WASM:
517 : case JAVA_SCRIPT:
518 : case OPTIMIZED:
519 : case INTERPRETED:
520 : default:
521 : // Unoptimized and optimized JavaScript frames, including
522 : // interpreted frames, should never have a StackFrame::Type
523 : // marker. If we find one, we're likely being called from the
524 : // profiler in a bogus stack frame.
525 : return NONE;
526 : }
527 : }
528 :
529 :
530 : #ifdef DEBUG
531 : bool StackFrame::can_access_heap_objects() const {
532 : return iterator_->can_access_heap_objects_;
533 : }
534 : #endif
535 :
536 :
537 90721014 : StackFrame::Type StackFrame::GetCallerState(State* state) const {
538 90721014 : ComputeCallerState(state);
539 90721006 : return ComputeType(iterator_, state);
540 : }
541 :
542 :
543 0 : Address StackFrame::UnpaddedFP() const {
544 0 : return fp();
545 : }
546 :
547 :
548 38370 : Code* EntryFrame::unchecked_code() const {
549 38370 : return isolate()->heap()->js_entry_code();
550 : }
551 :
552 :
553 5144 : void EntryFrame::ComputeCallerState(State* state) const {
554 5144 : GetCallerState(state);
555 5144 : }
556 :
557 :
558 0 : void EntryFrame::SetCallerFp(Address caller_fp) {
559 : const int offset = EntryFrameConstants::kCallerFPOffset;
560 0 : Memory::Address_at(this->fp() + offset) = caller_fp;
561 0 : }
562 :
563 :
564 3131207 : StackFrame::Type EntryFrame::GetCallerState(State* state) const {
565 : const int offset = EntryFrameConstants::kCallerFPOffset;
566 3131207 : Address fp = Memory::Address_at(this->fp() + offset);
567 3131207 : return ExitFrame::GetStateForFramePointer(fp, state);
568 : }
569 :
570 :
571 10 : Code* EntryConstructFrame::unchecked_code() const {
572 10 : return isolate()->heap()->js_construct_entry_code();
573 : }
574 :
575 :
576 0 : Object*& ExitFrame::code_slot() const {
577 : const int offset = ExitFrameConstants::kCodeOffset;
578 191799 : return Memory::Object_at(fp() + offset);
579 : }
580 :
581 38380 : Code* ExitFrame::unchecked_code() const {
582 38380 : return reinterpret_cast<Code*>(code_slot());
583 : }
584 :
585 :
586 20819122 : void ExitFrame::ComputeCallerState(State* state) const {
587 : // Set up the caller state.
588 62457366 : state->sp = caller_sp();
589 20819122 : state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
590 : state->pc_address = ResolveReturnAddressLocation(
591 41638244 : reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
592 20819122 : state->callee_pc_address = nullptr;
593 : if (FLAG_enable_embedded_constant_pool) {
594 : state->constant_pool_address = reinterpret_cast<Address*>(
595 : fp() + ExitFrameConstants::kConstantPoolOffset);
596 : }
597 20819122 : }
598 :
599 :
600 0 : void ExitFrame::SetCallerFp(Address caller_fp) {
601 0 : Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
602 0 : }
603 :
604 153419 : void ExitFrame::Iterate(RootVisitor* v) const {
605 : // The arguments are traversed as part of the expression stack of
606 : // the calling frame.
607 153419 : IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
608 306838 : v->VisitRootPointer(Root::kTop, &code_slot());
609 153419 : }
610 :
611 :
612 20820822 : Address ExitFrame::GetCallerStackPointer() const {
613 20820822 : return fp() + ExitFrameConstants::kCallerSPOffset;
614 : }
615 :
616 :
617 22605686 : StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
618 22605686 : if (fp == 0) return NONE;
619 : Address sp = ComputeStackPointer(fp);
620 : FillState(fp, sp, state);
621 : DCHECK_NOT_NULL(*state->pc_address);
622 :
623 20401207 : return ComputeFrameType(fp);
624 : }
625 :
626 0 : StackFrame::Type ExitFrame::ComputeFrameType(Address fp) {
627 : // Distinguish between between regular and builtin exit frames.
628 : // Default to EXIT in all hairy cases (e.g., when called from profiler).
629 : const int offset = ExitFrameConstants::kFrameTypeOffset;
630 20401207 : Object* marker = Memory::Object_at(fp + offset);
631 :
632 20401207 : if (!marker->IsSmi()) {
633 : return EXIT;
634 : }
635 :
636 : intptr_t marker_int = bit_cast<intptr_t>(marker);
637 :
638 20401207 : StackFrame::Type frame_type = static_cast<StackFrame::Type>(marker_int >> 1);
639 20401207 : if (frame_type == EXIT || frame_type == BUILTIN_EXIT) {
640 0 : return frame_type;
641 : }
642 :
643 : return EXIT;
644 : }
645 :
646 0 : Address ExitFrame::ComputeStackPointer(Address fp) {
647 : MSAN_MEMORY_IS_INITIALIZED(fp + ExitFrameConstants::kSPOffset, kPointerSize);
648 20619792 : return Memory::Address_at(fp + ExitFrameConstants::kSPOffset);
649 : }
650 :
651 0 : void ExitFrame::FillState(Address fp, Address sp, State* state) {
652 20401207 : state->sp = sp;
653 20401207 : state->fp = fp;
654 : state->pc_address = ResolveReturnAddressLocation(
655 41020498 : reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
656 20401207 : state->callee_pc_address = nullptr;
657 : // The constant pool recorded in the exit frame is not associated
658 : // with the pc in this state (the return address into a C entry
659 : // stub). ComputeCallerState will retrieve the constant pool
660 : // together with the associated caller pc.
661 20401207 : state->constant_pool_address = nullptr;
662 0 : }
663 :
664 110478 : JSFunction* BuiltinExitFrame::function() const {
665 110478 : return JSFunction::cast(target_slot_object());
666 : }
667 :
668 106080 : Object* BuiltinExitFrame::receiver() const { return receiver_slot_object(); }
669 :
670 53040 : bool BuiltinExitFrame::IsConstructor() const {
671 106080 : return !new_target_slot_object()->IsUndefined(isolate());
672 : }
673 :
674 0 : Object* BuiltinExitFrame::GetParameter(int i) const {
675 : DCHECK(i >= 0 && i < ComputeParametersCount());
676 0 : int offset = BuiltinExitFrameConstants::kArgcOffset + (i + 1) * kPointerSize;
677 0 : return Memory::Object_at(fp() + offset);
678 : }
679 :
680 0 : int BuiltinExitFrame::ComputeParametersCount() const {
681 : Object* argc_slot = argc_slot_object();
682 : DCHECK(argc_slot->IsSmi());
683 : // Argc also counts the receiver, target, new target, and argc itself as args,
684 : // therefore the real argument count is argc - 4.
685 0 : int argc = Smi::cast(argc_slot)->value() - 4;
686 : DCHECK(argc >= 0);
687 0 : return argc;
688 : }
689 :
690 0 : void BuiltinExitFrame::Print(StringStream* accumulator, PrintMode mode,
691 : int index) const {
692 : DisallowHeapAllocation no_gc;
693 : Object* receiver = this->receiver();
694 : JSFunction* function = this->function();
695 :
696 0 : accumulator->PrintSecurityTokenIfChanged(function);
697 : PrintIndex(accumulator, mode, index);
698 0 : accumulator->Add("builtin exit frame: ");
699 0 : Code* code = NULL;
700 0 : if (IsConstructor()) accumulator->Add("new ");
701 0 : accumulator->PrintFunction(function, receiver, &code);
702 :
703 0 : accumulator->Add("(this=%o", receiver);
704 :
705 : // Print the parameters.
706 : int parameters_count = ComputeParametersCount();
707 0 : for (int i = 0; i < parameters_count; i++) {
708 0 : accumulator->Add(",%o", GetParameter(i));
709 : }
710 :
711 0 : accumulator->Add(")\n\n");
712 0 : }
713 :
714 6115621 : Address StandardFrame::GetExpressionAddress(int n) const {
715 : const int offset = StandardFrameConstants::kExpressionsOffset;
716 6115621 : return fp() + offset - n * kPointerSize;
717 : }
718 :
719 27386800 : Address InterpretedFrame::GetExpressionAddress(int n) const {
720 : const int offset = InterpreterFrameConstants::kExpressionsOffset;
721 27386800 : return fp() + offset - n * kPointerSize;
722 : }
723 :
724 0 : Script* StandardFrame::script() const {
725 : // This should only be called on frames which override this method.
726 : DCHECK(false);
727 0 : return nullptr;
728 : }
729 :
730 0 : Object* StandardFrame::receiver() const {
731 0 : return isolate()->heap()->undefined_value();
732 : }
733 :
734 98 : Object* StandardFrame::context() const {
735 98 : return isolate()->heap()->undefined_value();
736 : }
737 :
738 0 : int StandardFrame::position() const {
739 : AbstractCode* code = AbstractCode::cast(LookupCode());
740 0 : int code_offset = static_cast<int>(pc() - code->instruction_start());
741 0 : return code->SourcePosition(code_offset);
742 : }
743 :
744 0 : int StandardFrame::ComputeExpressionsCount() const {
745 10 : Address base = GetExpressionAddress(0);
746 10 : Address limit = sp() - kPointerSize;
747 : DCHECK(base >= limit); // stack grows downwards
748 : // Include register-allocated locals in number of expressions.
749 10 : return static_cast<int>((base - limit) / kPointerSize);
750 : }
751 :
752 0 : Object* StandardFrame::GetParameter(int index) const {
753 : // StandardFrame does not define any parameters.
754 0 : UNREACHABLE();
755 : return nullptr;
756 : }
757 :
758 0 : int StandardFrame::ComputeParametersCount() const { return 0; }
759 :
760 70805707 : void StandardFrame::ComputeCallerState(State* state) const {
761 354028535 : state->sp = caller_sp();
762 70805707 : state->fp = caller_fp();
763 : state->pc_address = ResolveReturnAddressLocation(
764 141611414 : reinterpret_cast<Address*>(ComputePCAddress(fp())));
765 70805707 : state->callee_pc_address = pc_address();
766 : state->constant_pool_address =
767 70805707 : reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
768 70805707 : }
769 :
770 :
771 0 : void StandardFrame::SetCallerFp(Address caller_fp) {
772 0 : Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
773 0 : caller_fp;
774 0 : }
775 :
776 0 : bool StandardFrame::IsConstructor() const { return false; }
777 :
778 0 : void StandardFrame::Summarize(List<FrameSummary>* functions,
779 : FrameSummary::Mode mode) const {
780 : // This should only be called on frames which override this method.
781 0 : UNREACHABLE();
782 : }
783 :
784 1665019 : void StandardFrame::IterateCompiledFrame(RootVisitor* v) const {
785 : // Make sure that we're not doing "safe" stack frame iteration. We cannot
786 : // possibly find pointers in optimized frames in that state.
787 : DCHECK(can_access_heap_objects());
788 :
789 : // Compute the safepoint information.
790 1665019 : unsigned stack_slots = 0;
791 : SafepointEntry safepoint_entry;
792 : Code* code = StackFrame::GetSafepointData(
793 6660076 : isolate(), pc(), &safepoint_entry, &stack_slots);
794 1665019 : unsigned slot_space = stack_slots * kPointerSize;
795 :
796 : // Determine the fixed header and spill slot area size.
797 : int frame_header_size = StandardFrameConstants::kFixedFrameSizeFromFp;
798 : intptr_t marker =
799 1665019 : Memory::intptr_at(fp() + CommonFrameConstants::kContextOrFrameTypeOffset);
800 1665019 : if (StackFrame::IsTypeMarker(marker)) {
801 : StackFrame::Type candidate = StackFrame::MarkerToType(marker);
802 1339156 : switch (candidate) {
803 : case ENTRY:
804 : case ENTRY_CONSTRUCT:
805 : case EXIT:
806 : case BUILTIN_EXIT:
807 : case STUB_FAILURE_TRAMPOLINE:
808 : case ARGUMENTS_ADAPTOR:
809 : case STUB:
810 : case INTERNAL:
811 : case CONSTRUCT:
812 : case JS_TO_WASM:
813 : case WASM_TO_JS:
814 : case WASM_COMPILED:
815 : case WASM_INTERPRETER_ENTRY:
816 : frame_header_size = TypedFrameConstants::kFixedFrameSizeFromFp;
817 1339156 : break;
818 : case JAVA_SCRIPT:
819 : case OPTIMIZED:
820 : case INTERPRETED:
821 : case BUILTIN:
822 : // These frame types have a context, but they are actually stored
823 : // in the place on the stack that one finds the frame type.
824 0 : UNREACHABLE();
825 : break;
826 : case NONE:
827 : case NUMBER_OF_TYPES:
828 : case MANUAL:
829 0 : UNREACHABLE();
830 : break;
831 : }
832 : }
833 : slot_space -=
834 1665019 : (frame_header_size + StandardFrameConstants::kFixedFrameSizeAboveFp);
835 :
836 1665019 : Object** frame_header_base = &Memory::Object_at(fp() - frame_header_size);
837 : Object** frame_header_limit =
838 : &Memory::Object_at(fp() - StandardFrameConstants::kCPSlotSize);
839 : Object** parameters_base = &Memory::Object_at(sp());
840 1665019 : Object** parameters_limit = frame_header_base - slot_space / kPointerSize;
841 :
842 : // Visit the parameters that may be on top of the saved registers.
843 3330038 : if (safepoint_entry.argument_count() > 0) {
844 : v->VisitRootPointers(Root::kTop, parameters_base,
845 681 : parameters_base + safepoint_entry.argument_count());
846 1362 : parameters_base += safepoint_entry.argument_count();
847 : }
848 :
849 : // Skip saved double registers.
850 3330038 : if (safepoint_entry.has_doubles()) {
851 : // Number of doubles not known at snapshot time.
852 : DCHECK(!isolate()->serializer_enabled());
853 0 : parameters_base += RegisterConfiguration::Crankshaft()
854 : ->num_allocatable_double_registers() *
855 0 : kDoubleSize / kPointerSize;
856 : }
857 :
858 : // Visit the registers that contain pointers if any.
859 1665019 : if (safepoint_entry.HasRegisters()) {
860 241920 : for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
861 241920 : if (safepoint_entry.HasRegisterAt(i)) {
862 : int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
863 56138 : v->VisitRootPointer(Root::kTop, parameters_base + reg_stack_index);
864 : }
865 : }
866 : // Skip the words containing the register values.
867 15120 : parameters_base += kNumSafepointRegisters;
868 : }
869 :
870 : // We're done dealing with the register bits.
871 1665019 : uint8_t* safepoint_bits = safepoint_entry.bits();
872 1665019 : safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
873 :
874 : // Visit the rest of the parameters if they are tagged.
875 1665019 : if (code->has_tagged_params()) {
876 1646140 : v->VisitRootPointers(Root::kTop, parameters_base, parameters_limit);
877 : }
878 :
879 : // Visit pointer spill slots and locals.
880 7196484 : for (unsigned index = 0; index < stack_slots; index++) {
881 7196484 : int byte_index = index >> kBitsPerByteLog2;
882 7196484 : int bit_index = index & (kBitsPerByte - 1);
883 7196484 : if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
884 321064 : v->VisitRootPointer(Root::kTop, parameters_limit + index);
885 : }
886 : }
887 :
888 : // Visit the return address in the callee and incoming arguments.
889 : IteratePc(v, pc_address(), constant_pool_address(), code);
890 :
891 4985650 : if (!is_wasm() && !is_wasm_to_js()) {
892 : // If this frame has JavaScript ABI, visit the context (in stub and JS
893 : // frames) and the function (in JS frames).
894 1646296 : v->VisitRootPointers(Root::kTop, frame_header_base, frame_header_limit);
895 : }
896 1665019 : }
897 :
898 1339221 : void StubFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); }
899 :
900 219176 : Code* StubFrame::unchecked_code() const {
901 219176 : return isolate()->FindCodeObject(pc());
902 : }
903 :
904 :
905 28793676 : Address StubFrame::GetCallerStackPointer() const {
906 28793676 : return fp() + ExitFrameConstants::kCallerSPOffset;
907 : }
908 :
909 :
910 0 : int StubFrame::GetNumberOfIncomingArguments() const {
911 0 : return 0;
912 : }
913 :
914 54 : int StubFrame::LookupExceptionHandlerInTable(int* stack_slots) {
915 : Code* code = LookupCode();
916 : DCHECK(code->is_turbofanned());
917 : DCHECK_EQ(code->kind(), Code::BUILTIN);
918 : HandlerTable* table = HandlerTable::cast(code->handler_table());
919 54 : int pc_offset = static_cast<int>(pc() - code->entry());
920 54 : *stack_slots = code->stack_slots();
921 54 : return table->LookupReturn(pc_offset);
922 : }
923 :
924 316391 : void OptimizedFrame::Iterate(RootVisitor* v) const { IterateCompiledFrame(v); }
925 :
926 2448 : void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
927 2448 : Memory::Object_at(GetParameterSlot(index)) = value;
928 2448 : }
929 :
930 :
931 14160732 : bool JavaScriptFrame::IsConstructor() const {
932 : Address fp = caller_fp();
933 14160732 : if (has_adapted_arguments()) {
934 : // Skip the arguments adaptor frame and look at the real caller.
935 1182874 : fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
936 : }
937 14160732 : return IsConstructFrame(fp);
938 : }
939 :
940 :
941 0 : bool JavaScriptFrame::HasInlinedFrames() const {
942 : List<SharedFunctionInfo*> functions(1);
943 0 : GetFunctions(&functions);
944 0 : return functions.length() > 1;
945 : }
946 :
947 :
948 12 : int JavaScriptFrame::GetArgumentsLength() const {
949 : // If there is an arguments adaptor frame get the arguments length from it.
950 12 : if (has_adapted_arguments()) {
951 12 : return ArgumentsAdaptorFrame::GetLength(caller_fp());
952 : } else {
953 0 : return GetNumberOfIncomingArguments();
954 : }
955 : }
956 :
957 :
958 373023 : Code* JavaScriptFrame::unchecked_code() const {
959 746046 : return function()->code();
960 : }
961 :
962 :
963 13144112 : int JavaScriptFrame::GetNumberOfIncomingArguments() const {
964 : DCHECK(can_access_heap_objects() &&
965 : isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
966 :
967 26288224 : return function()->shared()->internal_formal_parameter_count();
968 : }
969 :
970 :
971 53731287 : Address JavaScriptFrame::GetCallerStackPointer() const {
972 53731287 : return fp() + StandardFrameConstants::kCallerSPOffset;
973 : }
974 :
975 483964 : void JavaScriptFrame::GetFunctions(List<SharedFunctionInfo*>* functions) const {
976 : DCHECK(functions->length() == 0);
977 967928 : functions->Add(function()->shared());
978 483964 : }
979 :
980 54086 : void JavaScriptFrame::GetFunctions(
981 : List<Handle<SharedFunctionInfo>>* functions) const {
982 : DCHECK(functions->length() == 0);
983 : List<SharedFunctionInfo*> raw_functions;
984 54086 : GetFunctions(&raw_functions);
985 162427 : for (const auto& raw_function : raw_functions) {
986 108510 : functions->Add(Handle<SharedFunctionInfo>(raw_function));
987 : }
988 54086 : }
989 :
990 3202926 : void JavaScriptFrame::Summarize(List<FrameSummary>* functions,
991 : FrameSummary::Mode mode) const {
992 : DCHECK(functions->length() == 0);
993 3202926 : Code* code = LookupCode();
994 3202926 : int offset = static_cast<int>(pc() - code->instruction_start());
995 : AbstractCode* abstract_code = AbstractCode::cast(code);
996 3202926 : FrameSummary::JavaScriptFrameSummary summary(isolate(), receiver(),
997 3202926 : function(), abstract_code,
998 12811704 : offset, IsConstructor(), mode);
999 3202926 : functions->Add(summary);
1000 3202926 : }
1001 :
1002 86176654 : JSFunction* JavaScriptFrame::function() const {
1003 86176654 : return JSFunction::cast(function_slot_object());
1004 : }
1005 :
1006 12603414 : Object* JavaScriptFrame::receiver() const { return GetParameter(-1); }
1007 :
1008 808886 : Object* JavaScriptFrame::context() const {
1009 : const int offset = StandardFrameConstants::kContextOffset;
1010 808886 : Object* maybe_result = Memory::Object_at(fp() + offset);
1011 : DCHECK(!maybe_result->IsSmi());
1012 808886 : return maybe_result;
1013 : }
1014 :
1015 0 : Script* JavaScriptFrame::script() const {
1016 0 : return Script::cast(function()->shared()->script());
1017 : }
1018 :
1019 3428070 : int JavaScriptFrame::LookupExceptionHandlerInTable(
1020 : int* stack_depth, HandlerTable::CatchPrediction* prediction) {
1021 : DCHECK_EQ(0, LookupCode()->handler_table()->length());
1022 : DCHECK(!LookupCode()->is_optimized_code());
1023 3428070 : return -1;
1024 : }
1025 :
1026 0 : void JavaScriptFrame::PrintFunctionAndOffset(JSFunction* function,
1027 : AbstractCode* code,
1028 : int code_offset, FILE* file,
1029 : bool print_line_number) {
1030 0 : PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
1031 0 : function->PrintName(file);
1032 0 : PrintF(file, "+%d", code_offset);
1033 0 : if (print_line_number) {
1034 : SharedFunctionInfo* shared = function->shared();
1035 0 : int source_pos = code->SourcePosition(code_offset);
1036 : Object* maybe_script = shared->script();
1037 0 : if (maybe_script->IsScript()) {
1038 : Script* script = Script::cast(maybe_script);
1039 0 : int line = script->GetLineNumber(source_pos) + 1;
1040 : Object* script_name_raw = script->name();
1041 0 : if (script_name_raw->IsString()) {
1042 : String* script_name = String::cast(script->name());
1043 : std::unique_ptr<char[]> c_script_name =
1044 0 : script_name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL);
1045 0 : PrintF(file, " at %s:%d", c_script_name.get(), line);
1046 : } else {
1047 0 : PrintF(file, " at <unknown>:%d", line);
1048 : }
1049 : } else {
1050 0 : PrintF(file, " at <unknown>:<unknown>");
1051 : }
1052 : }
1053 0 : }
1054 :
1055 0 : void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
1056 : bool print_line_number) {
1057 : // constructor calls
1058 : DisallowHeapAllocation no_allocation;
1059 0 : JavaScriptFrameIterator it(isolate);
1060 0 : while (!it.done()) {
1061 0 : if (it.frame()->is_java_script()) {
1062 : JavaScriptFrame* frame = it.frame();
1063 0 : if (frame->IsConstructor()) PrintF(file, "new ");
1064 0 : JSFunction* function = frame->function();
1065 : int code_offset = 0;
1066 0 : if (frame->is_interpreted()) {
1067 : InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame);
1068 : code_offset = iframe->GetBytecodeOffset();
1069 : } else {
1070 0 : Code* code = frame->unchecked_code();
1071 0 : code_offset = static_cast<int>(frame->pc() - code->instruction_start());
1072 : }
1073 : PrintFunctionAndOffset(function, function->abstract_code(), code_offset,
1074 0 : file, print_line_number);
1075 0 : if (print_args) {
1076 : // function arguments
1077 : // (we are intentionally only printing the actually
1078 : // supplied parameters, not all parameters required)
1079 0 : PrintF(file, "(this=");
1080 0 : frame->receiver()->ShortPrint(file);
1081 0 : const int length = frame->ComputeParametersCount();
1082 0 : for (int i = 0; i < length; i++) {
1083 0 : PrintF(file, ", ");
1084 0 : frame->GetParameter(i)->ShortPrint(file);
1085 : }
1086 0 : PrintF(file, ")");
1087 : }
1088 : break;
1089 : }
1090 0 : it.Advance();
1091 : }
1092 0 : }
1093 :
1094 0 : void JavaScriptFrame::CollectFunctionAndOffsetForICStats(JSFunction* function,
1095 : AbstractCode* code,
1096 : int code_offset) {
1097 : auto ic_stats = ICStats::instance();
1098 : ICInfo& ic_info = ic_stats->Current();
1099 : SharedFunctionInfo* shared = function->shared();
1100 :
1101 0 : ic_info.function_name = ic_stats->GetOrCacheFunctionName(function);
1102 0 : ic_info.script_offset = code_offset;
1103 :
1104 0 : int source_pos = code->SourcePosition(code_offset);
1105 : Object* maybe_script = shared->script();
1106 0 : if (maybe_script->IsScript()) {
1107 : Script* script = Script::cast(maybe_script);
1108 0 : ic_info.line_num = script->GetLineNumber(source_pos) + 1;
1109 0 : ic_info.script_name = ic_stats->GetOrCacheScriptName(script);
1110 : }
1111 0 : }
1112 :
1113 0 : void JavaScriptFrame::CollectTopFrameForICStats(Isolate* isolate) {
1114 : // constructor calls
1115 : DisallowHeapAllocation no_allocation;
1116 0 : JavaScriptFrameIterator it(isolate);
1117 : ICInfo& ic_info = ICStats::instance()->Current();
1118 0 : while (!it.done()) {
1119 0 : if (it.frame()->is_java_script()) {
1120 : JavaScriptFrame* frame = it.frame();
1121 0 : if (frame->IsConstructor()) ic_info.is_constructor = true;
1122 0 : JSFunction* function = frame->function();
1123 : int code_offset = 0;
1124 0 : if (frame->is_interpreted()) {
1125 : InterpretedFrame* iframe = reinterpret_cast<InterpretedFrame*>(frame);
1126 : code_offset = iframe->GetBytecodeOffset();
1127 : } else {
1128 0 : Code* code = frame->unchecked_code();
1129 0 : code_offset = static_cast<int>(frame->pc() - code->instruction_start());
1130 : }
1131 : CollectFunctionAndOffsetForICStats(function, function->abstract_code(),
1132 0 : code_offset);
1133 0 : return;
1134 : }
1135 0 : it.Advance();
1136 : }
1137 : }
1138 :
1139 15520628 : Object* JavaScriptFrame::GetParameter(int index) const {
1140 15520628 : return Memory::Object_at(GetParameterSlot(index));
1141 : }
1142 :
1143 15905286 : int JavaScriptFrame::ComputeParametersCount() const {
1144 15905286 : return GetNumberOfIncomingArguments();
1145 : }
1146 :
1147 : namespace {
1148 :
1149 : bool CannotDeoptFromAsmCode(Code* code, JSFunction* function) {
1150 2619568 : return code->is_turbofanned() && function->shared()->asm_function();
1151 : }
1152 :
1153 : } // namespace
1154 :
1155 14369805 : FrameSummary::JavaScriptFrameSummary::JavaScriptFrameSummary(
1156 : Isolate* isolate, Object* receiver, JSFunction* function,
1157 : AbstractCode* abstract_code, int code_offset, bool is_constructor,
1158 : Mode mode)
1159 : : FrameSummaryBase(isolate, JAVA_SCRIPT),
1160 : receiver_(receiver, isolate),
1161 : function_(function, isolate),
1162 : abstract_code_(abstract_code, isolate),
1163 : code_offset_(code_offset),
1164 14369805 : is_constructor_(is_constructor) {
1165 : DCHECK(abstract_code->IsBytecodeArray() ||
1166 : Code::cast(abstract_code)->kind() != Code::OPTIMIZED_FUNCTION ||
1167 : CannotDeoptFromAsmCode(Code::cast(abstract_code), function) ||
1168 : mode == kApproximateSummary);
1169 14369805 : }
1170 :
1171 0 : bool FrameSummary::JavaScriptFrameSummary::is_subject_to_debugging() const {
1172 6240134 : return function()->shared()->IsSubjectToDebugging();
1173 : }
1174 :
1175 1410161 : int FrameSummary::JavaScriptFrameSummary::SourcePosition() const {
1176 1410161 : return abstract_code()->SourcePosition(code_offset());
1177 : }
1178 :
1179 65971 : int FrameSummary::JavaScriptFrameSummary::SourceStatementPosition() const {
1180 65971 : return abstract_code()->SourceStatementPosition(code_offset());
1181 : }
1182 :
1183 1215219 : Handle<Object> FrameSummary::JavaScriptFrameSummary::script() const {
1184 2430438 : return handle(function_->shared()->script(), isolate());
1185 : }
1186 :
1187 47006 : Handle<String> FrameSummary::JavaScriptFrameSummary::FunctionName() const {
1188 47006 : return JSFunction::GetDebugName(function_);
1189 : }
1190 :
1191 12655 : Handle<Context> FrameSummary::JavaScriptFrameSummary::native_context() const {
1192 25310 : return handle(function_->context()->native_context(), isolate());
1193 : }
1194 :
1195 0 : FrameSummary::WasmFrameSummary::WasmFrameSummary(
1196 : Isolate* isolate, FrameSummary::Kind kind,
1197 : Handle<WasmInstanceObject> instance, bool at_to_number_conversion)
1198 : : FrameSummaryBase(isolate, kind),
1199 : wasm_instance_(instance),
1200 75647 : at_to_number_conversion_(at_to_number_conversion) {}
1201 :
1202 0 : Handle<Object> FrameSummary::WasmFrameSummary::receiver() const {
1203 0 : return wasm_instance_->GetIsolate()->global_proxy();
1204 : }
1205 :
1206 : #define WASM_SUMMARY_DISPATCH(type, name) \
1207 : type FrameSummary::WasmFrameSummary::name() const { \
1208 : DCHECK(kind() == Kind::WASM_COMPILED || kind() == Kind::WASM_INTERPRETED); \
1209 : return kind() == Kind::WASM_COMPILED \
1210 : ? static_cast<const WasmCompiledFrameSummary*>(this)->name() \
1211 : : static_cast<const WasmInterpretedFrameSummary*>(this) \
1212 : ->name(); \
1213 : }
1214 :
1215 38058 : WASM_SUMMARY_DISPATCH(uint32_t, function_index)
1216 38076 : WASM_SUMMARY_DISPATCH(int, byte_offset)
1217 :
1218 : #undef WASM_SUMMARY_DISPATCH
1219 :
1220 37361 : int FrameSummary::WasmFrameSummary::SourcePosition() const {
1221 37214 : int offset = byte_offset();
1222 : Handle<WasmCompiledModule> compiled_module(wasm_instance()->compiled_module(),
1223 74428 : isolate());
1224 37214 : if (compiled_module->is_asm_js()) {
1225 : offset = WasmCompiledModule::GetAsmJsSourcePosition(
1226 294 : compiled_module, function_index(), offset, at_to_number_conversion());
1227 : } else {
1228 37067 : offset += compiled_module->GetFunctionOffset(function_index());
1229 : }
1230 37214 : return offset;
1231 : }
1232 :
1233 37449 : Handle<Script> FrameSummary::WasmFrameSummary::script() const {
1234 74898 : return handle(wasm_instance()->compiled_module()->script());
1235 : }
1236 :
1237 374 : Handle<String> FrameSummary::WasmFrameSummary::FunctionName() const {
1238 : Handle<WasmCompiledModule> compiled_module(
1239 374 : wasm_instance()->compiled_module());
1240 : return WasmCompiledModule::GetFunctionName(compiled_module->GetIsolate(),
1241 374 : compiled_module, function_index());
1242 : }
1243 :
1244 49 : Handle<Context> FrameSummary::WasmFrameSummary::native_context() const {
1245 49 : return wasm_instance()->compiled_module()->native_context();
1246 : }
1247 :
1248 0 : FrameSummary::WasmCompiledFrameSummary::WasmCompiledFrameSummary(
1249 : Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> code,
1250 : int code_offset, bool at_to_number_conversion)
1251 : : WasmFrameSummary(isolate, WASM_COMPILED, instance,
1252 : at_to_number_conversion),
1253 : code_(code),
1254 0 : code_offset_(code_offset) {}
1255 :
1256 74308 : uint32_t FrameSummary::WasmCompiledFrameSummary::function_index() const {
1257 : FixedArray* deopt_data = code()->deoptimization_data();
1258 : DCHECK_EQ(2, deopt_data->length());
1259 : DCHECK(deopt_data->get(1)->IsSmi());
1260 : int val = Smi::cast(deopt_data->get(1))->value();
1261 : DCHECK_LE(0, val);
1262 74308 : return static_cast<uint32_t>(val);
1263 : }
1264 :
1265 36822 : int FrameSummary::WasmCompiledFrameSummary::byte_offset() const {
1266 36822 : return AbstractCode::cast(*code())->SourcePosition(code_offset());
1267 : }
1268 :
1269 0 : FrameSummary::WasmInterpretedFrameSummary::WasmInterpretedFrameSummary(
1270 : Isolate* isolate, Handle<WasmInstanceObject> instance,
1271 : uint32_t function_index, int byte_offset)
1272 : : WasmFrameSummary(isolate, WASM_INTERPRETED, instance, false),
1273 : function_index_(function_index),
1274 0 : byte_offset_(byte_offset) {}
1275 :
1276 21936970 : FrameSummary::~FrameSummary() {
1277 : #define FRAME_SUMMARY_DESTR(kind, type, field, desc) \
1278 : case kind: \
1279 : field.~type(); \
1280 : break;
1281 21936970 : switch (base_.kind()) {
1282 : FRAME_SUMMARY_VARIANTS(FRAME_SUMMARY_DESTR)
1283 : default:
1284 0 : UNREACHABLE();
1285 : }
1286 : #undef FRAME_SUMMARY_DESTR
1287 21936970 : }
1288 :
1289 1070685 : FrameSummary FrameSummary::GetTop(const StandardFrame* frame) {
1290 1070685 : List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
1291 1070685 : frame->Summarize(&frames);
1292 : DCHECK_LT(0, frames.length());
1293 2141370 : return frames.last();
1294 : }
1295 :
1296 0 : FrameSummary FrameSummary::GetBottom(const StandardFrame* frame) {
1297 0 : return Get(frame, 0);
1298 : }
1299 :
1300 37339 : FrameSummary FrameSummary::GetSingle(const StandardFrame* frame) {
1301 : List<FrameSummary> frames(1);
1302 37339 : frame->Summarize(&frames);
1303 : DCHECK_EQ(1, frames.length());
1304 74678 : return frames.first();
1305 : }
1306 :
1307 451502 : FrameSummary FrameSummary::Get(const StandardFrame* frame, int index) {
1308 : DCHECK_LE(0, index);
1309 451502 : List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
1310 451502 : frame->Summarize(&frames);
1311 : DCHECK_GT(frames.length(), index);
1312 1354506 : return frames[index];
1313 : }
1314 :
1315 : #define FRAME_SUMMARY_DISPATCH(ret, name) \
1316 : ret FrameSummary::name() const { \
1317 : switch (base_.kind()) { \
1318 : case JAVA_SCRIPT: \
1319 : return java_script_summary_.name(); \
1320 : case WASM_COMPILED: \
1321 : return wasm_compiled_summary_.name(); \
1322 : case WASM_INTERPRETED: \
1323 : return wasm_interpreted_summary_.name(); \
1324 : default: \
1325 : UNREACHABLE(); \
1326 : return ret{}; \
1327 : } \
1328 : }
1329 :
1330 4906594 : FRAME_SUMMARY_DISPATCH(Handle<Object>, receiver)
1331 5156146 : FRAME_SUMMARY_DISPATCH(int, code_offset)
1332 229173 : FRAME_SUMMARY_DISPATCH(bool, is_constructor)
1333 6243772 : FRAME_SUMMARY_DISPATCH(bool, is_subject_to_debugging)
1334 1239778 : FRAME_SUMMARY_DISPATCH(Handle<Object>, script)
1335 1471493 : FRAME_SUMMARY_DISPATCH(int, SourcePosition)
1336 65971 : FRAME_SUMMARY_DISPATCH(int, SourceStatementPosition)
1337 472 : FRAME_SUMMARY_DISPATCH(Handle<String>, FunctionName)
1338 12704 : FRAME_SUMMARY_DISPATCH(Handle<Context>, native_context)
1339 :
1340 : #undef FRAME_SUMMARY_DISPATCH
1341 :
1342 1588993 : void OptimizedFrame::Summarize(List<FrameSummary>* frames,
1343 : FrameSummary::Mode mode) const {
1344 : DCHECK(frames->length() == 0);
1345 : DCHECK(is_optimized());
1346 :
1347 : // Delegate to JS frame in absence of turbofan deoptimization.
1348 : // TODO(turbofan): Revisit once we support deoptimization across the board.
1349 1609142 : Code* code = LookupCode();
1350 2961777 : if (code->kind() == Code::BUILTIN ||
1351 1372784 : CannotDeoptFromAsmCode(code, function())) {
1352 433306 : return JavaScriptFrame::Summarize(frames);
1353 : }
1354 :
1355 : DisallowHeapAllocation no_gc;
1356 1372340 : int deopt_index = Safepoint::kNoDeoptimizationIndex;
1357 1372340 : DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
1358 1372340 : if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
1359 : DCHECK(data == nullptr);
1360 0 : if (mode == FrameSummary::kApproximateSummary) {
1361 0 : return JavaScriptFrame::Summarize(frames, mode);
1362 : }
1363 0 : FATAL("Missing deoptimization information for OptimizedFrame::Summarize.");
1364 : }
1365 : FixedArray* const literal_array = data->LiteralArray();
1366 :
1367 : TranslationIterator it(data->TranslationByteArray(),
1368 1372340 : data->TranslationIndex(deopt_index)->value());
1369 : Translation::Opcode frame_opcode =
1370 1372340 : static_cast<Translation::Opcode>(it.Next());
1371 : DCHECK_EQ(Translation::BEGIN, frame_opcode);
1372 1372340 : it.Next(); // Drop frame count.
1373 1372340 : int jsframe_count = it.Next();
1374 :
1375 : // We create the summary in reverse order because the frames
1376 : // in the deoptimization translation are ordered bottom-to-top.
1377 1372340 : bool is_constructor = IsConstructor();
1378 6445741 : while (jsframe_count != 0) {
1379 3701061 : frame_opcode = static_cast<Translation::Opcode>(it.Next());
1380 3701061 : if (frame_opcode == Translation::JS_FRAME ||
1381 : frame_opcode == Translation::INTERPRETED_FRAME) {
1382 1581455 : jsframe_count--;
1383 1581455 : BailoutId const bailout_id = BailoutId(it.Next());
1384 : SharedFunctionInfo* const shared_info =
1385 1581455 : SharedFunctionInfo::cast(literal_array->get(it.Next()));
1386 1581455 : it.Next(); // Skip height.
1387 :
1388 : // The translation commands are ordered and the function is always
1389 : // at the first position, and the receiver is next.
1390 1581455 : Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
1391 :
1392 : // Get the correct function in the optimized frame.
1393 : JSFunction* function;
1394 1581455 : if (opcode == Translation::LITERAL) {
1395 160499 : function = JSFunction::cast(literal_array->get(it.Next()));
1396 : } else {
1397 1420956 : CHECK_EQ(opcode, Translation::STACK_SLOT);
1398 1420956 : function = JSFunction::cast(StackSlotAt(it.Next()));
1399 : }
1400 : DCHECK_EQ(shared_info, function->shared());
1401 :
1402 : // If we are at a call, the receiver is always in a stack slot.
1403 : // Otherwise we are not guaranteed to get the receiver value.
1404 1581455 : opcode = static_cast<Translation::Opcode>(it.Next());
1405 :
1406 : // Get the correct receiver in the optimized frame.
1407 : Object* receiver;
1408 1581455 : if (opcode == Translation::LITERAL) {
1409 135083 : receiver = literal_array->get(it.Next());
1410 1446372 : } else if (opcode == Translation::STACK_SLOT) {
1411 1418685 : receiver = StackSlotAt(it.Next());
1412 : } else {
1413 : // The receiver is not in a stack slot nor in a literal. We give up.
1414 27687 : it.Skip(Translation::NumberOfOperandsFor(opcode));
1415 : // TODO(3029): Materializing a captured object (or duplicated
1416 : // object) is hard, we return undefined for now. This breaks the
1417 : // produced stack trace, as constructor frames aren't marked as
1418 : // such anymore.
1419 27687 : receiver = isolate()->heap()->undefined_value();
1420 : }
1421 :
1422 : AbstractCode* abstract_code;
1423 :
1424 : unsigned code_offset;
1425 1581455 : if (frame_opcode == Translation::JS_FRAME) {
1426 : Code* code = shared_info->code();
1427 : DeoptimizationOutputData* const output_data =
1428 : DeoptimizationOutputData::cast(code->deoptimization_data());
1429 : unsigned const entry =
1430 534365 : Deoptimizer::GetOutputInfo(output_data, bailout_id, shared_info);
1431 : code_offset = FullCodeGenerator::PcField::decode(entry);
1432 : abstract_code = AbstractCode::cast(code);
1433 : } else {
1434 : DCHECK_EQ(frame_opcode, Translation::INTERPRETED_FRAME);
1435 1047090 : code_offset = bailout_id.ToInt(); // Points to current bytecode.
1436 : abstract_code = AbstractCode::cast(shared_info->bytecode_array());
1437 : }
1438 : FrameSummary::JavaScriptFrameSummary summary(isolate(), receiver,
1439 : function, abstract_code,
1440 3162910 : code_offset, is_constructor);
1441 1581455 : frames->Add(summary);
1442 : is_constructor = false;
1443 2119606 : } else if (frame_opcode == Translation::CONSTRUCT_STUB_FRAME) {
1444 : // The next encountered JS_FRAME will be marked as a constructor call.
1445 18121 : it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
1446 : DCHECK(!is_constructor);
1447 : is_constructor = true;
1448 : } else {
1449 : // Skip over operands to advance to the next opcode.
1450 2101485 : it.Skip(Translation::NumberOfOperandsFor(frame_opcode));
1451 : }
1452 : }
1453 : DCHECK(!is_constructor);
1454 : }
1455 :
1456 :
1457 2088497 : int OptimizedFrame::LookupExceptionHandlerInTable(
1458 : int* stack_slots, HandlerTable::CatchPrediction* prediction) {
1459 : // We cannot perform exception prediction on optimized code. Instead, we need
1460 : // to use FrameSummary to find the corresponding code offset in unoptimized
1461 : // code to perform prediction there.
1462 : DCHECK_NULL(prediction);
1463 : Code* code = LookupCode();
1464 : HandlerTable* table = HandlerTable::cast(code->handler_table());
1465 2088497 : int pc_offset = static_cast<int>(pc() - code->entry());
1466 4077656 : if (stack_slots) *stack_slots = code->stack_slots();
1467 2088497 : return table->LookupReturn(pc_offset);
1468 : }
1469 :
1470 :
1471 1628175 : DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
1472 : int* deopt_index) const {
1473 : DCHECK(is_optimized());
1474 :
1475 1628175 : JSFunction* opt_function = function();
1476 1628175 : Code* code = opt_function->code();
1477 :
1478 : // The code object may have been replaced by lazy deoptimization. Fall
1479 : // back to a slow search in this case to find the original optimized
1480 : // code object.
1481 1800365 : if (!code->contains(pc())) {
1482 : code = isolate()->inner_pointer_to_code_cache()->
1483 172190 : GcSafeFindCodeForInnerPointer(pc());
1484 : }
1485 : DCHECK(code != NULL);
1486 : DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
1487 :
1488 1628175 : SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1489 3256350 : *deopt_index = safepoint_entry.deoptimization_index();
1490 1628175 : if (*deopt_index != Safepoint::kNoDeoptimizationIndex) {
1491 1628175 : return DeoptimizationInputData::cast(code->deoptimization_data());
1492 : }
1493 : return nullptr;
1494 : }
1495 :
1496 229223 : Object* OptimizedFrame::receiver() const {
1497 216223 : Code* code = LookupCode();
1498 229223 : if (code->kind() == Code::BUILTIN) {
1499 : Address argc_ptr = fp() + OptimizedBuiltinFrameConstants::kArgCOffset;
1500 216223 : intptr_t argc = *reinterpret_cast<intptr_t*>(argc_ptr);
1501 : intptr_t args_size =
1502 216223 : (StandardFrameConstants::kFixedSlotCountAboveFp + argc) * kPointerSize;
1503 216223 : Address receiver_ptr = fp() + args_size;
1504 216223 : return *reinterpret_cast<Object**>(receiver_ptr);
1505 : } else {
1506 26000 : return JavaScriptFrame::receiver();
1507 : }
1508 : }
1509 :
1510 196754 : void OptimizedFrame::GetFunctions(List<SharedFunctionInfo*>* functions) const {
1511 : DCHECK(functions->length() == 0);
1512 : DCHECK(is_optimized());
1513 :
1514 : // Delegate to JS frame in absence of turbofan deoptimization.
1515 : // TODO(turbofan): Revisit once we support deoptimization across the board.
1516 : Code* code = LookupCode();
1517 390832 : if (code->kind() == Code::BUILTIN ||
1518 194078 : CannotDeoptFromAsmCode(code, function())) {
1519 200264 : return JavaScriptFrame::GetFunctions(functions);
1520 : }
1521 :
1522 : DisallowHeapAllocation no_gc;
1523 193244 : int deopt_index = Safepoint::kNoDeoptimizationIndex;
1524 193244 : DeoptimizationInputData* const data = GetDeoptimizationData(&deopt_index);
1525 : DCHECK_NOT_NULL(data);
1526 : DCHECK_NE(Safepoint::kNoDeoptimizationIndex, deopt_index);
1527 : FixedArray* const literal_array = data->LiteralArray();
1528 :
1529 : TranslationIterator it(data->TranslationByteArray(),
1530 193244 : data->TranslationIndex(deopt_index)->value());
1531 193244 : Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
1532 : DCHECK_EQ(Translation::BEGIN, opcode);
1533 193244 : it.Next(); // Skip frame count.
1534 193244 : int jsframe_count = it.Next();
1535 :
1536 : // We insert the frames in reverse order because the frames
1537 : // in the deoptimization translation are ordered bottom-to-top.
1538 582273 : while (jsframe_count != 0) {
1539 195785 : opcode = static_cast<Translation::Opcode>(it.Next());
1540 195785 : if (opcode == Translation::JS_FRAME ||
1541 : opcode == Translation::INTERPRETED_FRAME) {
1542 193643 : it.Next(); // Skip bailout id.
1543 193643 : jsframe_count--;
1544 :
1545 : // The second operand of the frame points to the function.
1546 193643 : Object* shared = literal_array->get(it.Next());
1547 193643 : functions->Add(SharedFunctionInfo::cast(shared));
1548 :
1549 : // Skip over remaining operands to advance to the next opcode.
1550 193643 : it.Skip(Translation::NumberOfOperandsFor(opcode) - 2);
1551 : } else {
1552 : // Skip over operands to advance to the next opcode.
1553 2142 : it.Skip(Translation::NumberOfOperandsFor(opcode));
1554 : }
1555 : }
1556 : }
1557 :
1558 :
1559 1224534 : int OptimizedFrame::StackSlotOffsetRelativeToFp(int slot_index) {
1560 4064175 : return StandardFrameConstants::kCallerSPOffset -
1561 4064175 : ((slot_index + 1) * kPointerSize);
1562 : }
1563 :
1564 :
1565 0 : Object* OptimizedFrame::StackSlotAt(int index) const {
1566 5679282 : return Memory::Object_at(fp() + StackSlotOffsetRelativeToFp(index));
1567 : }
1568 :
1569 0 : int InterpretedFrame::position() const {
1570 : AbstractCode* code = AbstractCode::cast(GetBytecodeArray());
1571 : int code_offset = GetBytecodeOffset();
1572 0 : return code->SourcePosition(code_offset);
1573 : }
1574 :
1575 4723091 : int InterpretedFrame::LookupExceptionHandlerInTable(
1576 : int* context_register, HandlerTable::CatchPrediction* prediction) {
1577 4723091 : BytecodeArray* bytecode = function()->shared()->bytecode_array();
1578 : HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
1579 4723091 : return table->LookupRange(GetBytecodeOffset(), context_register, prediction);
1580 : }
1581 :
1582 252286 : int InterpretedFrame::GetBytecodeOffset() const {
1583 : const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1584 : DCHECK_EQ(
1585 : InterpreterFrameConstants::kBytecodeOffsetFromFp,
1586 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1587 14560801 : int raw_offset = Smi::cast(GetExpression(index))->value();
1588 14560817 : return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
1589 : }
1590 :
1591 0 : int InterpretedFrame::GetBytecodeOffset(Address fp) {
1592 : const int offset = InterpreterFrameConstants::kExpressionsOffset;
1593 : const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1594 : DCHECK_EQ(
1595 : InterpreterFrameConstants::kBytecodeOffsetFromFp,
1596 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1597 : Address expression_offset = fp + offset - index * kPointerSize;
1598 0 : int raw_offset = Smi::cast(Memory::Object_at(expression_offset))->value();
1599 0 : return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
1600 : }
1601 :
1602 919886 : void InterpretedFrame::PatchBytecodeOffset(int new_offset) {
1603 : const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
1604 : DCHECK_EQ(
1605 : InterpreterFrameConstants::kBytecodeOffsetFromFp,
1606 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1607 919886 : int raw_offset = new_offset + BytecodeArray::kHeaderSize - kHeapObjectTag;
1608 919886 : SetExpression(index, Smi::FromInt(raw_offset));
1609 919886 : }
1610 :
1611 4747968 : BytecodeArray* InterpretedFrame::GetBytecodeArray() const {
1612 : const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1613 : DCHECK_EQ(
1614 : InterpreterFrameConstants::kBytecodeArrayFromFp,
1615 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1616 9495952 : return BytecodeArray::cast(GetExpression(index));
1617 : }
1618 :
1619 2196 : void InterpretedFrame::PatchBytecodeArray(BytecodeArray* bytecode_array) {
1620 : const int index = InterpreterFrameConstants::kBytecodeArrayExpressionIndex;
1621 : DCHECK_EQ(
1622 : InterpreterFrameConstants::kBytecodeArrayFromFp,
1623 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1624 2196 : SetExpression(index, bytecode_array);
1625 2196 : }
1626 :
1627 919886 : Object* InterpretedFrame::ReadInterpreterRegister(int register_index) const {
1628 : const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1629 : DCHECK_EQ(
1630 : InterpreterFrameConstants::kRegisterFileFromFp,
1631 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1632 1839772 : return GetExpression(index + register_index);
1633 : }
1634 :
1635 0 : void InterpretedFrame::WriteInterpreterRegister(int register_index,
1636 : Object* value) {
1637 : const int index = InterpreterFrameConstants::kRegisterFileExpressionIndex;
1638 : DCHECK_EQ(
1639 : InterpreterFrameConstants::kRegisterFileFromFp,
1640 : InterpreterFrameConstants::kExpressionsOffset - index * kPointerSize);
1641 0 : return SetExpression(index + register_index, value);
1642 : }
1643 :
1644 9585424 : void InterpretedFrame::Summarize(List<FrameSummary>* functions,
1645 : FrameSummary::Mode mode) const {
1646 : DCHECK(functions->length() == 0);
1647 : AbstractCode* abstract_code =
1648 9585424 : AbstractCode::cast(function()->shared()->bytecode_array());
1649 : FrameSummary::JavaScriptFrameSummary summary(
1650 19170848 : isolate(), receiver(), function(), abstract_code, GetBytecodeOffset(),
1651 28756272 : IsConstructor());
1652 9585424 : functions->Add(summary);
1653 9585424 : }
1654 :
1655 2757075 : int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
1656 5514150 : return Smi::cast(GetExpression(0))->value();
1657 : }
1658 :
1659 0 : int ArgumentsAdaptorFrame::GetLength(Address fp) {
1660 : const int offset = ArgumentsAdaptorFrameConstants::kLengthOffset;
1661 12 : return Smi::cast(Memory::Object_at(fp + offset))->value();
1662 : }
1663 :
1664 40839 : Code* ArgumentsAdaptorFrame::unchecked_code() const {
1665 : return isolate()->builtins()->builtin(
1666 81678 : Builtins::kArgumentsAdaptorTrampoline);
1667 : }
1668 :
1669 4099 : int BuiltinFrame::GetNumberOfIncomingArguments() const {
1670 8198 : return Smi::cast(GetExpression(0))->value();
1671 : }
1672 :
1673 0 : void BuiltinFrame::PrintFrameKind(StringStream* accumulator) const {
1674 0 : accumulator->Add("builtin frame: ");
1675 0 : }
1676 :
1677 5483341 : Address InternalFrame::GetCallerStackPointer() const {
1678 : // Internal frames have no arguments. The stack pointer of the
1679 : // caller is at a fixed offset from the frame pointer.
1680 5483341 : return fp() + StandardFrameConstants::kCallerSPOffset;
1681 : }
1682 :
1683 47339 : Code* InternalFrame::unchecked_code() const {
1684 : const int offset = InternalFrameConstants::kCodeOffset;
1685 47339 : Object* code = Memory::Object_at(fp() + offset);
1686 : DCHECK(code != NULL);
1687 47339 : return reinterpret_cast<Code*>(code);
1688 : }
1689 :
1690 :
1691 0 : void StackFrame::PrintIndex(StringStream* accumulator,
1692 : PrintMode mode,
1693 : int index) {
1694 42 : accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1695 0 : }
1696 :
1697 0 : void WasmCompiledFrame::Print(StringStream* accumulator, PrintMode mode,
1698 : int index) const {
1699 : PrintIndex(accumulator, mode, index);
1700 0 : accumulator->Add("WASM [");
1701 0 : Script* script = this->script();
1702 0 : accumulator->PrintName(script->name());
1703 0 : int pc = static_cast<int>(this->pc() - LookupCode()->instruction_start());
1704 0 : Object* instance = this->wasm_instance();
1705 : Vector<const uint8_t> raw_func_name =
1706 : WasmInstanceObject::cast(instance)->compiled_module()->GetRawFunctionName(
1707 0 : this->function_index());
1708 0 : const int kMaxPrintedFunctionName = 64;
1709 : char func_name[kMaxPrintedFunctionName + 1];
1710 0 : int func_name_len = std::min(kMaxPrintedFunctionName, raw_func_name.length());
1711 0 : memcpy(func_name, raw_func_name.start(), func_name_len);
1712 0 : func_name[func_name_len] = '\0';
1713 : accumulator->Add("], function #%u ('%s'), pc=%p, pos=%d\n",
1714 0 : this->function_index(), func_name, pc, this->position());
1715 0 : if (mode != OVERVIEW) accumulator->Add("\n");
1716 0 : }
1717 :
1718 42028 : Code* WasmCompiledFrame::unchecked_code() const {
1719 42028 : return isolate()->FindCodeObject(pc());
1720 : }
1721 :
1722 9407 : void WasmCompiledFrame::Iterate(RootVisitor* v) const {
1723 9407 : IterateCompiledFrame(v);
1724 9407 : }
1725 :
1726 2498610 : Address WasmCompiledFrame::GetCallerStackPointer() const {
1727 2498610 : return fp() + ExitFrameConstants::kCallerSPOffset;
1728 : }
1729 :
1730 112986 : WasmInstanceObject* WasmCompiledFrame::wasm_instance() const {
1731 112986 : WasmInstanceObject* obj = wasm::GetOwningWasmInstance(LookupCode());
1732 : // This is a live stack frame; it must have a live instance.
1733 : DCHECK_NOT_NULL(obj);
1734 112986 : return obj;
1735 : }
1736 :
1737 37339 : uint32_t WasmCompiledFrame::function_index() const {
1738 37339 : return FrameSummary::GetSingle(this).AsWasmCompiled().function_index();
1739 : }
1740 :
1741 0 : Script* WasmCompiledFrame::script() const {
1742 0 : return wasm_instance()->compiled_module()->script();
1743 : }
1744 :
1745 0 : int WasmCompiledFrame::position() const {
1746 0 : return FrameSummary::GetSingle(this).SourcePosition();
1747 : }
1748 :
1749 75647 : void WasmCompiledFrame::Summarize(List<FrameSummary>* functions,
1750 : FrameSummary::Mode mode) const {
1751 : DCHECK_EQ(0, functions->length());
1752 226941 : Handle<Code> code(LookupCode(), isolate());
1753 151294 : int offset = static_cast<int>(pc() - code->instruction_start());
1754 75647 : Handle<WasmInstanceObject> instance(wasm_instance(), isolate());
1755 : FrameSummary::WasmCompiledFrameSummary summary(
1756 75647 : isolate(), instance, code, offset, at_to_number_conversion());
1757 75647 : functions->Add(summary);
1758 75647 : }
1759 :
1760 76366 : bool WasmCompiledFrame::at_to_number_conversion() const {
1761 : // Check whether our callee is a WASM_TO_JS frame, and this frame is at the
1762 : // ToNumber conversion call.
1763 79956 : Address callee_pc = reinterpret_cast<Address>(this->callee_pc());
1764 79956 : Code* code = callee_pc ? isolate()->FindCodeObject(callee_pc) : nullptr;
1765 79956 : if (!code || code->kind() != Code::WASM_TO_JS_FUNCTION) return false;
1766 1387 : int offset = static_cast<int>(callee_pc - code->instruction_start());
1767 1387 : int pos = AbstractCode::cast(code)->SourcePosition(offset);
1768 : DCHECK(pos == 0 || pos == 1);
1769 : // The imported call has position 0, ToNumber has position 1.
1770 1387 : return !!pos;
1771 : }
1772 :
1773 1830 : int WasmCompiledFrame::LookupExceptionHandlerInTable(int* stack_slots) {
1774 : DCHECK_NOT_NULL(stack_slots);
1775 : Code* code = LookupCode();
1776 : HandlerTable* table = HandlerTable::cast(code->handler_table());
1777 1830 : int pc_offset = static_cast<int>(pc() - code->entry());
1778 1830 : *stack_slots = code->stack_slots();
1779 1830 : return table->LookupReturn(pc_offset);
1780 : }
1781 :
1782 0 : void WasmInterpreterEntryFrame::Iterate(RootVisitor* v) const {
1783 0 : IterateCompiledFrame(v);
1784 0 : }
1785 :
1786 0 : void WasmInterpreterEntryFrame::Print(StringStream* accumulator, PrintMode mode,
1787 : int index) const {
1788 : PrintIndex(accumulator, mode, index);
1789 0 : accumulator->Add("WASM INTERPRETER ENTRY [");
1790 0 : Script* script = this->script();
1791 0 : accumulator->PrintName(script->name());
1792 0 : accumulator->Add("]");
1793 0 : if (mode != OVERVIEW) accumulator->Add("\n");
1794 0 : }
1795 :
1796 2470 : void WasmInterpreterEntryFrame::Summarize(List<FrameSummary>* functions,
1797 : FrameSummary::Mode mode) const {
1798 991324 : Handle<WasmInstanceObject> instance(wasm_instance(), isolate());
1799 : std::vector<std::pair<uint32_t, int>> interpreted_stack =
1800 2470 : instance->debug_info()->GetInterpretedStack(fp());
1801 :
1802 991324 : for (auto& e : interpreted_stack) {
1803 : FrameSummary::WasmInterpretedFrameSummary summary(isolate(), instance,
1804 986384 : e.first, e.second);
1805 986384 : functions->Add(summary);
1806 : }
1807 2470 : }
1808 :
1809 0 : Code* WasmInterpreterEntryFrame::unchecked_code() const {
1810 0 : return isolate()->FindCodeObject(pc());
1811 : }
1812 :
1813 4101 : WasmInstanceObject* WasmInterpreterEntryFrame::wasm_instance() const {
1814 4101 : WasmInstanceObject* ret = wasm::GetOwningWasmInstance(LookupCode());
1815 : // This is a live stack frame, there must be a live wasm instance available.
1816 : DCHECK_NOT_NULL(ret);
1817 4101 : return ret;
1818 : }
1819 :
1820 0 : Script* WasmInterpreterEntryFrame::script() const {
1821 0 : return wasm_instance()->compiled_module()->script();
1822 : }
1823 :
1824 0 : int WasmInterpreterEntryFrame::position() const {
1825 0 : return FrameSummary::GetBottom(this).AsWasmInterpreted().SourcePosition();
1826 : }
1827 :
1828 0 : Object* WasmInterpreterEntryFrame::context() const {
1829 0 : return wasm_instance()->compiled_module()->ptr_to_native_context();
1830 : }
1831 :
1832 6319 : Address WasmInterpreterEntryFrame::GetCallerStackPointer() const {
1833 6319 : return fp() + ExitFrameConstants::kCallerSPOffset;
1834 : }
1835 :
1836 : namespace {
1837 :
1838 :
1839 21 : void PrintFunctionSource(StringStream* accumulator, SharedFunctionInfo* shared,
1840 : Code* code) {
1841 21 : if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1842 21 : std::ostringstream os;
1843 21 : os << "--------- s o u r c e c o d e ---------\n"
1844 63 : << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1845 21 : << "\n-----------------------------------------\n";
1846 42 : accumulator->Add(os.str().c_str());
1847 : }
1848 21 : }
1849 :
1850 :
1851 : } // namespace
1852 :
1853 :
1854 42 : void JavaScriptFrame::Print(StringStream* accumulator,
1855 : PrintMode mode,
1856 : int index) const {
1857 : DisallowHeapAllocation no_gc;
1858 42 : Object* receiver = this->receiver();
1859 42 : JSFunction* function = this->function();
1860 :
1861 42 : accumulator->PrintSecurityTokenIfChanged(function);
1862 : PrintIndex(accumulator, mode, index);
1863 42 : PrintFrameKind(accumulator);
1864 42 : Code* code = NULL;
1865 42 : if (IsConstructor()) accumulator->Add("new ");
1866 42 : accumulator->PrintFunction(function, receiver, &code);
1867 :
1868 : // Get scope information for nicer output, if possible. If code is NULL, or
1869 : // doesn't contain scope info, scope_info will return 0 for the number of
1870 : // parameters, stack local variables, context local variables, stack slots,
1871 : // or context slots.
1872 : SharedFunctionInfo* shared = function->shared();
1873 : ScopeInfo* scope_info = shared->scope_info();
1874 : Object* script_obj = shared->script();
1875 42 : if (script_obj->IsScript()) {
1876 : Script* script = Script::cast(script_obj);
1877 28 : accumulator->Add(" [");
1878 28 : accumulator->PrintName(script->name());
1879 :
1880 : Address pc = this->pc();
1881 88 : if (code != NULL && code->kind() == Code::FUNCTION &&
1882 36 : pc >= code->instruction_start() && pc < code->instruction_end()) {
1883 4 : int offset = static_cast<int>(pc - code->instruction_start());
1884 4 : int source_pos = AbstractCode::cast(code)->SourcePosition(offset);
1885 4 : int line = script->GetLineNumber(source_pos) + 1;
1886 4 : accumulator->Add(":%d] [pc=%p]", line, pc);
1887 48 : } else if (is_interpreted()) {
1888 : const InterpretedFrame* iframe =
1889 : reinterpret_cast<const InterpretedFrame*>(this);
1890 : BytecodeArray* bytecodes = iframe->GetBytecodeArray();
1891 : int offset = iframe->GetBytecodeOffset();
1892 16 : int source_pos = AbstractCode::cast(bytecodes)->SourcePosition(offset);
1893 16 : int line = script->GetLineNumber(source_pos) + 1;
1894 16 : accumulator->Add(":%d] [bytecode=%p offset=%d]", line, bytecodes, offset);
1895 : } else {
1896 : int function_start_pos = shared->start_position();
1897 8 : int line = script->GetLineNumber(function_start_pos) + 1;
1898 8 : accumulator->Add(":~%d] [pc=%p]", line, pc);
1899 : }
1900 : }
1901 :
1902 42 : accumulator->Add("(this=%o", receiver);
1903 :
1904 : // Print the parameters.
1905 42 : int parameters_count = ComputeParametersCount();
1906 140 : for (int i = 0; i < parameters_count; i++) {
1907 98 : accumulator->Add(",");
1908 : // If we have a name for the parameter we print it. Nameless
1909 : // parameters are either because we have more actual parameters
1910 : // than formal parameters or because we have no scope information.
1911 98 : if (i < scope_info->ParameterCount()) {
1912 0 : accumulator->PrintName(scope_info->ParameterName(i));
1913 0 : accumulator->Add("=");
1914 : }
1915 98 : accumulator->Add("%o", GetParameter(i));
1916 : }
1917 :
1918 42 : accumulator->Add(")");
1919 42 : if (mode == OVERVIEW) {
1920 21 : accumulator->Add("\n");
1921 21 : return;
1922 : }
1923 42 : if (is_optimized()) {
1924 11 : accumulator->Add(" {\n// optimized frame\n");
1925 11 : PrintFunctionSource(accumulator, shared, code);
1926 11 : accumulator->Add("}\n");
1927 11 : return;
1928 : }
1929 10 : accumulator->Add(" {\n");
1930 :
1931 : // Compute the number of locals and expression stack elements.
1932 10 : int stack_locals_count = scope_info->StackLocalCount();
1933 10 : int heap_locals_count = scope_info->ContextLocalCount();
1934 10 : int expressions_count = ComputeExpressionsCount();
1935 :
1936 : // Print stack-allocated local variables.
1937 10 : if (stack_locals_count > 0) {
1938 0 : accumulator->Add(" // stack-allocated locals\n");
1939 : }
1940 0 : for (int i = 0; i < stack_locals_count; i++) {
1941 0 : accumulator->Add(" var ");
1942 0 : accumulator->PrintName(scope_info->StackLocalName(i));
1943 0 : accumulator->Add(" = ");
1944 0 : if (i < expressions_count) {
1945 0 : accumulator->Add("%o", GetExpression(i));
1946 : } else {
1947 0 : accumulator->Add("// no expression found - inconsistent frame?");
1948 : }
1949 0 : accumulator->Add("\n");
1950 : }
1951 :
1952 : // Try to get hold of the context of this frame.
1953 : Context* context = NULL;
1954 20 : if (this->context() != NULL && this->context()->IsContext()) {
1955 10 : context = Context::cast(this->context());
1956 : }
1957 10 : while (context->IsWithContext()) {
1958 : context = context->previous();
1959 : DCHECK(context != NULL);
1960 : }
1961 :
1962 : // Print heap-allocated local variables.
1963 10 : if (heap_locals_count > 0) {
1964 0 : accumulator->Add(" // heap-allocated locals\n");
1965 : }
1966 0 : for (int i = 0; i < heap_locals_count; i++) {
1967 0 : accumulator->Add(" var ");
1968 0 : accumulator->PrintName(scope_info->ContextLocalName(i));
1969 0 : accumulator->Add(" = ");
1970 0 : if (context != NULL) {
1971 0 : int index = Context::MIN_CONTEXT_SLOTS + i;
1972 0 : if (index < context->length()) {
1973 0 : accumulator->Add("%o", context->get(index));
1974 : } else {
1975 : accumulator->Add(
1976 0 : "// warning: missing context slot - inconsistent frame?");
1977 : }
1978 : } else {
1979 0 : accumulator->Add("// warning: no context found - inconsistent frame?");
1980 : }
1981 0 : accumulator->Add("\n");
1982 : }
1983 :
1984 : // Print the expression stack.
1985 : int expressions_start = stack_locals_count;
1986 10 : if (expressions_start < expressions_count) {
1987 0 : accumulator->Add(" // expression stack (top to bottom)\n");
1988 : }
1989 10 : for (int i = expressions_count - 1; i >= expressions_start; i--) {
1990 0 : accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1991 : }
1992 :
1993 10 : PrintFunctionSource(accumulator, shared, code);
1994 :
1995 10 : accumulator->Add("}\n\n");
1996 : }
1997 :
1998 :
1999 0 : void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
2000 : PrintMode mode,
2001 : int index) const {
2002 0 : int actual = ComputeParametersCount();
2003 : int expected = -1;
2004 0 : JSFunction* function = this->function();
2005 : expected = function->shared()->internal_formal_parameter_count();
2006 :
2007 : PrintIndex(accumulator, mode, index);
2008 0 : accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
2009 0 : if (mode == OVERVIEW) {
2010 0 : accumulator->Add("\n");
2011 0 : return;
2012 : }
2013 0 : accumulator->Add(" {\n");
2014 :
2015 : // Print actual arguments.
2016 0 : if (actual > 0) accumulator->Add(" // actual arguments\n");
2017 0 : for (int i = 0; i < actual; i++) {
2018 0 : accumulator->Add(" [%02d] : %o", i, GetParameter(i));
2019 0 : if (expected != -1 && i >= expected) {
2020 0 : accumulator->Add(" // not passed to callee");
2021 : }
2022 0 : accumulator->Add("\n");
2023 : }
2024 :
2025 0 : accumulator->Add("}\n\n");
2026 : }
2027 :
2028 153419 : void EntryFrame::Iterate(RootVisitor* v) const {
2029 153419 : IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
2030 153419 : }
2031 :
2032 0 : void StandardFrame::IterateExpressions(RootVisitor* v) const {
2033 : const int offset = StandardFrameConstants::kLastObjectOffset;
2034 2541146 : Object** base = &Memory::Object_at(sp());
2035 : Object** limit = &Memory::Object_at(fp() + offset) + 1;
2036 2541146 : v->VisitRootPointers(Root::kTop, base, limit);
2037 0 : }
2038 :
2039 2365644 : void JavaScriptFrame::Iterate(RootVisitor* v) const {
2040 : IterateExpressions(v);
2041 2365644 : IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
2042 2365644 : }
2043 :
2044 175502 : void InternalFrame::Iterate(RootVisitor* v) const {
2045 175502 : Code* code = LookupCode();
2046 : IteratePc(v, pc_address(), constant_pool_address(), code);
2047 : // Internal frames typically do not receive any arguments, hence their stack
2048 : // only contains tagged pointers.
2049 : // We are misusing the has_tagged_params flag here to tell us whether
2050 : // the full stack frame contains only tagged pointers or only raw values.
2051 : // This is used for the WasmCompileLazy builtin, where we actually pass
2052 : // untagged arguments and also store untagged values on the stack.
2053 175502 : if (code->has_tagged_params()) IterateExpressions(v);
2054 175502 : }
2055 :
2056 0 : void StubFailureTrampolineFrame::Iterate(RootVisitor* v) const {
2057 0 : Object** base = &Memory::Object_at(sp());
2058 : Object** limit = &Memory::Object_at(
2059 0 : fp() + StubFailureTrampolineFrameConstants::kFixedHeaderBottomOffset);
2060 0 : v->VisitRootPointers(Root::kTop, base, limit);
2061 0 : base = &Memory::Object_at(fp() + StandardFrameConstants::kFunctionOffset);
2062 : const int offset = StandardFrameConstants::kLastObjectOffset;
2063 : limit = &Memory::Object_at(fp() + offset) + 1;
2064 0 : v->VisitRootPointers(Root::kTop, base, limit);
2065 : IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
2066 0 : }
2067 :
2068 :
2069 219 : Address StubFailureTrampolineFrame::GetCallerStackPointer() const {
2070 219 : return fp() + StandardFrameConstants::kCallerSPOffset;
2071 : }
2072 :
2073 :
2074 0 : Code* StubFailureTrampolineFrame::unchecked_code() const {
2075 : Code* trampoline;
2076 : StubFailureTrampolineStub(isolate(), NOT_JS_FUNCTION_STUB_MODE).
2077 0 : FindCodeInCache(&trampoline);
2078 0 : if (trampoline->contains(pc())) {
2079 0 : return trampoline;
2080 : }
2081 :
2082 : StubFailureTrampolineStub(isolate(), JS_FUNCTION_STUB_MODE).
2083 0 : FindCodeInCache(&trampoline);
2084 0 : if (trampoline->contains(pc())) {
2085 0 : return trampoline;
2086 : }
2087 :
2088 0 : UNREACHABLE();
2089 : return NULL;
2090 : }
2091 :
2092 :
2093 : // -------------------------------------------------------------------------
2094 :
2095 :
2096 0 : JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
2097 : DCHECK(n >= 0);
2098 0 : for (int i = 0; i <= n; i++) {
2099 0 : while (!iterator_.frame()->is_java_script()) iterator_.Advance();
2100 0 : if (i == n) return JavaScriptFrame::cast(iterator_.frame());
2101 0 : iterator_.Advance();
2102 : }
2103 0 : UNREACHABLE();
2104 : return NULL;
2105 : }
2106 :
2107 :
2108 : // -------------------------------------------------------------------------
2109 :
2110 :
2111 33061803 : static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
2112 : MapWord map_word = object->map_word();
2113 : return map_word.IsForwardingAddress() ?
2114 66123606 : map_word.ToForwardingAddress()->map() : map_word.ToMap();
2115 : }
2116 :
2117 :
2118 33061803 : static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
2119 33061803 : return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
2120 : }
2121 :
2122 :
2123 : #ifdef DEBUG
2124 : static bool GcSafeCodeContains(HeapObject* code, Address addr) {
2125 : Map* map = GcSafeMapOfCodeSpaceObject(code);
2126 : DCHECK(map == code->GetHeap()->code_map());
2127 : Address start = code->address();
2128 : Address end = code->address() + code->SizeFromMap(map);
2129 : return start <= addr && addr < end;
2130 : }
2131 : #endif
2132 :
2133 :
2134 0 : Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
2135 : Address inner_pointer) {
2136 : Code* code = reinterpret_cast<Code*>(object);
2137 : DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer));
2138 0 : return code;
2139 : }
2140 :
2141 :
2142 5663013 : Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
2143 : Address inner_pointer) {
2144 22652011 : Heap* heap = isolate_->heap();
2145 :
2146 : // Check if the inner pointer points into a large object chunk.
2147 5663013 : LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
2148 5663013 : if (large_page != NULL) {
2149 10 : return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
2150 : }
2151 :
2152 5663003 : if (!heap->code_space()->Contains(inner_pointer)) {
2153 : return nullptr;
2154 : }
2155 :
2156 : // Iterate through the page until we reach the end or find an object starting
2157 : // after the inner pointer.
2158 : Page* page = Page::FromAddress(inner_pointer);
2159 :
2160 : DCHECK_EQ(page->owner(), heap->code_space());
2161 5662999 : heap->mark_compact_collector()->sweeper().SweepOrWaitUntilSweepingCompleted(
2162 5662999 : page);
2163 :
2164 5662996 : Address addr = page->skip_list()->StartFor(inner_pointer);
2165 :
2166 : Address top = heap->code_space()->top();
2167 : Address limit = heap->code_space()->limit();
2168 :
2169 : while (true) {
2170 33064562 : if (addr == top && addr != limit) {
2171 : addr = limit;
2172 : continue;
2173 : }
2174 :
2175 33061803 : HeapObject* obj = HeapObject::FromAddress(addr);
2176 33061803 : int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
2177 33061802 : Address next_addr = addr + obj_size;
2178 33061802 : if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
2179 : addr = next_addr;
2180 : }
2181 : }
2182 :
2183 :
2184 : InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
2185 117966569 : InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
2186 230802763 : isolate_->counters()->pc_to_code()->Increment();
2187 : DCHECK(base::bits::IsPowerOfTwo32(kInnerPointerToCodeCacheSize));
2188 : uint32_t hash = ComputeIntegerHash(ObjectAddressForHashing(inner_pointer),
2189 : v8::internal::kZeroHashSeed);
2190 117966579 : uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
2191 117966579 : InnerPointerToCodeCacheEntry* entry = cache(index);
2192 117966579 : if (entry->inner_pointer == inner_pointer) {
2193 225672388 : isolate_->counters()->pc_to_code_cached()->Increment();
2194 : DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
2195 : } else {
2196 : // Because this code may be interrupted by a profiling signal that
2197 : // also queries the cache, we cannot update inner_pointer before the code
2198 : // has been set. Otherwise, we risk trying to use a cache entry before
2199 : // the code has been computed.
2200 5130385 : entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
2201 : entry->safepoint_entry.Reset();
2202 5130379 : entry->inner_pointer = inner_pointer;
2203 : }
2204 117966574 : return entry;
2205 : }
2206 :
2207 :
2208 : // -------------------------------------------------------------------------
2209 :
2210 :
2211 0 : int NumRegs(RegList reglist) { return base::bits::CountPopulation(reglist); }
2212 :
2213 :
2214 : struct JSCallerSavedCodeData {
2215 : int reg_code[kNumJSCallerSaved];
2216 : };
2217 :
2218 : JSCallerSavedCodeData caller_saved_code_data;
2219 :
2220 59461 : void SetUpJSCallerSavedCodeData() {
2221 : int i = 0;
2222 1010837 : for (int r = 0; r < kNumRegs; r++)
2223 951376 : if ((kJSCallerSaved & (1 << r)) != 0)
2224 297305 : caller_saved_code_data.reg_code[i++] = r;
2225 :
2226 : DCHECK(i == kNumJSCallerSaved);
2227 59461 : }
2228 :
2229 :
2230 0 : int JSCallerSavedCode(int n) {
2231 : DCHECK(0 <= n && n < kNumJSCallerSaved);
2232 0 : return caller_saved_code_data.reg_code[n];
2233 : }
2234 :
2235 :
2236 : #define DEFINE_WRAPPER(type, field) \
2237 : class field##_Wrapper : public ZoneObject { \
2238 : public: /* NOLINT */ \
2239 : field##_Wrapper(const field& original) : frame_(original) { \
2240 : } \
2241 : field frame_; \
2242 : };
2243 : STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
2244 : #undef DEFINE_WRAPPER
2245 :
2246 26844 : static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
2247 : #define FRAME_TYPE_CASE(type, field) \
2248 : case StackFrame::type: { \
2249 : field##_Wrapper* wrapper = \
2250 : new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
2251 : return &wrapper->frame_; \
2252 : }
2253 :
2254 26844 : switch (frame->type()) {
2255 26844 : STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
2256 0 : default: UNREACHABLE();
2257 : }
2258 : #undef FRAME_TYPE_CASE
2259 : return NULL;
2260 : }
2261 :
2262 :
2263 894 : Vector<StackFrame*> CreateStackMap(Isolate* isolate, Zone* zone) {
2264 894 : ZoneList<StackFrame*> list(10, zone);
2265 27738 : for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
2266 26844 : StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
2267 : list.Add(frame, zone);
2268 : }
2269 894 : return list.ToVector();
2270 : }
2271 :
2272 :
2273 : } // namespace internal
2274 : } // namespace v8
|