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