V8 Project
frames.cc
Go to the documentation of this file.
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/v8.h"
6 
7 #include "src/ast.h"
8 #include "src/base/bits.h"
9 #include "src/deoptimizer.h"
10 #include "src/frames-inl.h"
11 #include "src/full-codegen.h"
12 #include "src/heap/mark-compact.h"
13 #include "src/safepoint-table.h"
14 #include "src/scopeinfo.h"
15 #include "src/string-stream.h"
16 #include "src/vm-state-inl.h"
17 
18 namespace v8 {
19 namespace internal {
20 
21 
23  StackFrame::return_address_location_resolver_ = NULL;
24 
25 
26 // Iterator that supports traversing the stack handlers of a
27 // particular frame. Needs to know the top of the handler chain.
28 class StackHandlerIterator BASE_EMBEDDED {
29  public:
30  StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
31  : limit_(frame->fp()), handler_(handler) {
32  // Make sure the handler has already been unwound to this frame.
33  DCHECK(frame->sp() <= handler->address());
34  }
35 
36  StackHandler* handler() const { return handler_; }
37 
38  bool done() {
39  return handler_ == NULL || handler_->address() > limit_;
40  }
41  void Advance() {
42  DCHECK(!done());
43  handler_ = handler_->next();
44  }
45 
46  private:
47  const Address limit_;
48  StackHandler* handler_;
49 };
50 
51 
52 // -------------------------------------------------------------------------
53 
54 
55 #define INITIALIZE_SINGLETON(type, field) field##_(this),
56 StackFrameIteratorBase::StackFrameIteratorBase(Isolate* isolate,
57  bool can_access_heap_objects)
58  : isolate_(isolate),
60  frame_(NULL), handler_(NULL),
61  can_access_heap_objects_(can_access_heap_objects) {
62 }
63 #undef INITIALIZE_SINGLETON
64 
65 
66 StackFrameIterator::StackFrameIterator(Isolate* isolate)
67  : StackFrameIteratorBase(isolate, true) {
68  Reset(isolate->thread_local_top());
69 }
70 
71 
72 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
73  : StackFrameIteratorBase(isolate, true) {
74  Reset(t);
75 }
76 
77 
79  DCHECK(!done());
80  // Compute the state of the calling frame before restoring
81  // callee-saved registers and unwinding handlers. This allows the
82  // frame code that computes the caller state to access the top
83  // handler and the value of any callee-saved register if needed.
84  StackFrame::State state;
85  StackFrame::Type type = frame_->GetCallerState(&state);
86 
87  // Unwind handlers corresponding to the current frame.
88  StackHandlerIterator it(frame_, handler_);
89  while (!it.done()) it.Advance();
90  handler_ = it.handler();
91 
92  // Advance to the calling frame.
93  frame_ = SingletonFor(type, &state);
94 
95  // When we're done iterating over the stack frames, the handler
96  // chain must have been completely unwound.
97  DCHECK(!done() || handler_ == NULL);
98 }
99 
100 
101 void StackFrameIterator::Reset(ThreadLocalTop* top) {
102  StackFrame::State state;
104  Isolate::c_entry_fp(top), &state);
105  handler_ = StackHandler::FromAddress(Isolate::handler(top));
106  if (SingletonFor(type) == NULL) return;
107  frame_ = SingletonFor(type, &state);
108 }
109 
110 
111 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type,
112  StackFrame::State* state) {
113  if (type == StackFrame::NONE) return NULL;
114  StackFrame* result = SingletonFor(type);
115  DCHECK(result != NULL);
116  result->state_ = *state;
117  return result;
118 }
119 
120 
121 StackFrame* StackFrameIteratorBase::SingletonFor(StackFrame::Type type) {
122 #define FRAME_TYPE_CASE(type, field) \
123  case StackFrame::type: result = &field##_; break;
124 
125  StackFrame* result = NULL;
126  switch (type) {
127  case StackFrame::NONE: return NULL;
129  default: break;
130  }
131  return result;
132 
133 #undef FRAME_TYPE_CASE
134 }
135 
136 
137 // -------------------------------------------------------------------------
138 
139 
140 JavaScriptFrameIterator::JavaScriptFrameIterator(
141  Isolate* isolate, StackFrame::Id id)
142  : iterator_(isolate) {
143  while (!done()) {
144  Advance();
145  if (frame()->id() == id) return;
146  }
147 }
148 
149 
150 void JavaScriptFrameIterator::Advance() {
151  do {
152  iterator_.Advance();
153  } while (!iterator_.done() && !iterator_.frame()->is_java_script());
154 }
155 
156 
157 void JavaScriptFrameIterator::AdvanceToArgumentsFrame() {
158  if (!frame()->has_adapted_arguments()) return;
159  iterator_.Advance();
160  DCHECK(iterator_.frame()->is_arguments_adaptor());
161 }
162 
163 
164 // -------------------------------------------------------------------------
165 
166 
168  : JavaScriptFrameIterator(isolate) {
169  if (!done() && !IsValidFrame()) Advance();
170 }
171 
172 
174  while (true) {
175  JavaScriptFrameIterator::Advance();
176  if (done()) return;
177  if (IsValidFrame()) return;
178  }
179 }
180 
181 
183  if (!frame()->function()->IsJSFunction()) return false;
184  Object* script = frame()->function()->shared()->script();
185  // Don't show functions from native scripts to user.
186  return (script->IsScript() &&
187  Script::TYPE_NATIVE != Script::cast(script)->type()->value());
188 }
189 
190 
191 // -------------------------------------------------------------------------
192 
193 
195  Isolate* isolate,
196  Address fp, Address sp, Address js_entry_sp)
197  : StackFrameIteratorBase(isolate, false),
198  low_bound_(sp),
199  high_bound_(js_entry_sp),
200  top_frame_type_(StackFrame::NONE),
201  external_callback_scope_(isolate->external_callback_scope()) {
202  StackFrame::State state;
203  StackFrame::Type type;
204  ThreadLocalTop* top = isolate->thread_local_top();
205  if (IsValidTop(top)) {
207  top_frame_type_ = type;
208  } else if (IsValidStackAddress(fp)) {
209  DCHECK(fp != NULL);
210  state.fp = fp;
211  state.sp = sp;
212  state.pc_address = StackFrame::ResolveReturnAddressLocation(
213  reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp)));
214  // StackFrame::ComputeType will read both kContextOffset and kMarkerOffset,
215  // we check only that kMarkerOffset is within the stack bounds and do
216  // compile time check that kContextOffset slot is pushed on the stack before
217  // kMarkerOffset.
221  if (IsValidStackAddress(frame_marker)) {
222  type = StackFrame::ComputeType(this, &state);
223  top_frame_type_ = type;
224  } else {
225  // Mark the frame as JAVA_SCRIPT if we cannot determine its type.
226  // The frame anyways will be skipped.
227  type = StackFrame::JAVA_SCRIPT;
228  // Top frame is incomplete so we cannot reliably determine its type.
230  }
231  } else {
232  return;
233  }
234  if (SingletonFor(type) == NULL) return;
235  frame_ = SingletonFor(type, &state);
236  if (frame_ == NULL) return;
237 
238  Advance();
239 
240  if (frame_ != NULL && !frame_->is_exit() &&
242  external_callback_scope_->scope_address() < frame_->fp()) {
243  // Skip top ExternalCallbackScope if we already advanced to a JS frame
244  // under it. Sampler will anyways take this top external callback.
246  }
247 }
248 
249 
250 bool SafeStackFrameIterator::IsValidTop(ThreadLocalTop* top) const {
251  Address c_entry_fp = Isolate::c_entry_fp(top);
252  if (!IsValidExitFrame(c_entry_fp)) return false;
253  // There should be at least one JS_ENTRY stack handler.
254  Address handler = Isolate::handler(top);
255  if (handler == NULL) return false;
256  // Check that there are no js frames on top of the native frames.
257  return c_entry_fp < handler;
258 }
259 
260 
262  DCHECK(!done());
263  StackFrame* last_frame = frame_;
264  Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
265  // Before advancing to the next stack frame, perform pointer validity tests.
266  if (!IsValidFrame(last_frame) || !IsValidCaller(last_frame)) {
267  frame_ = NULL;
268  return;
269  }
270 
271  // Advance to the previous frame.
272  StackFrame::State state;
273  StackFrame::Type type = frame_->GetCallerState(&state);
274  frame_ = SingletonFor(type, &state);
275  if (frame_ == NULL) return;
276 
277  // Check that we have actually moved to the previous frame in the stack.
278  if (frame_->sp() < last_sp || frame_->fp() < last_fp) {
279  frame_ = NULL;
280  }
281 }
282 
283 
285  return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
286 }
287 
288 
290  StackFrame::State state;
291  if (frame->is_entry() || frame->is_entry_construct()) {
292  // See EntryFrame::GetCallerState. It computes the caller FP address
293  // and calls ExitFrame::GetStateForFramePointer on it. We need to be
294  // sure that caller FP address is valid.
295  Address caller_fp = Memory::Address_at(
297  if (!IsValidExitFrame(caller_fp)) return false;
298  } else if (frame->is_arguments_adaptor()) {
299  // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
300  // the number of arguments is stored on stack as Smi. We need to check
301  // that it really an Smi.
302  Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
303  GetExpression(0);
304  if (!number_of_args->IsSmi()) {
305  return false;
306  }
307  }
308  frame->ComputeCallerState(&state);
309  return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
310  SingletonFor(frame->GetCallerState(&state)) != NULL;
311 }
312 
313 
315  if (!IsValidStackAddress(fp)) return false;
317  if (!IsValidStackAddress(sp)) return false;
318  StackFrame::State state;
319  ExitFrame::FillState(fp, sp, &state);
320  if (!IsValidStackAddress(reinterpret_cast<Address>(state.pc_address))) {
321  return false;
322  }
323  return *state.pc_address != NULL;
324 }
325 
326 
328  while (true) {
329  AdvanceOneFrame();
330  if (done()) return;
331  if (frame_->is_java_script()) return;
332  if (frame_->is_exit() && external_callback_scope_) {
333  // Some of the EXIT frames may have ExternalCallbackScope allocated on
334  // top of them. In that case the scope corresponds to the first EXIT
335  // frame beneath it. There may be other EXIT frames on top of the
336  // ExternalCallbackScope, just skip them as we cannot collect any useful
337  // information about them.
338  if (external_callback_scope_->scope_address() < frame_->fp()) {
339  Address* callback_address =
340  external_callback_scope_->callback_address();
341  if (*callback_address != NULL) {
342  frame_->state_.pc_address = callback_address;
343  }
346  external_callback_scope_->scope_address() > frame_->fp());
347  return;
348  }
349  }
350  }
351 }
352 
353 
354 // -------------------------------------------------------------------------
355 
356 
357 Code* StackFrame::GetSafepointData(Isolate* isolate,
358  Address inner_pointer,
359  SafepointEntry* safepoint_entry,
360  unsigned* stack_slots) {
362  isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
363  if (!entry->safepoint_entry.is_valid()) {
364  entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
365  DCHECK(entry->safepoint_entry.is_valid());
366  } else {
367  DCHECK(entry->safepoint_entry.Equals(
368  entry->code->GetSafepointEntry(inner_pointer)));
369  }
370 
371  // Fill in the results and return the code.
372  Code* code = entry->code;
373  *safepoint_entry = entry->safepoint_entry;
374  *stack_slots = code->stack_slots();
375  return code;
376 }
377 
378 
379 bool StackFrame::HasHandler() const {
380  StackHandlerIterator it(this, top_handler());
381  return !it.done();
382 }
383 
384 
385 #ifdef DEBUG
386 static bool GcSafeCodeContains(HeapObject* object, Address addr);
387 #endif
388 
389 
390 void StackFrame::IteratePc(ObjectVisitor* v,
391  Address* pc_address,
392  Code* holder) {
393  Address pc = *pc_address;
394  DCHECK(GcSafeCodeContains(holder, pc));
395  unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
396  Object* code = holder;
397  v->VisitPointer(&code);
398  if (code != holder) {
399  holder = reinterpret_cast<Code*>(code);
400  pc = holder->instruction_start() + pc_offset;
401  *pc_address = pc;
402  }
403 }
404 
405 
406 void StackFrame::SetReturnAddressLocationResolver(
408  DCHECK(return_address_location_resolver_ == NULL);
409  return_address_location_resolver_ = resolver;
410 }
411 
412 
413 StackFrame::Type StackFrame::ComputeType(const StackFrameIteratorBase* iterator,
414  State* state) {
415  DCHECK(state->fp != NULL);
417  return ARGUMENTS_ADAPTOR;
418  }
419  // The marker and function offsets overlap. If the marker isn't a
420  // smi then the frame is a JavaScript frame -- and the marker is
421  // really the function.
422  const int offset = StandardFrameConstants::kMarkerOffset;
423  Object* marker = Memory::Object_at(state->fp + offset);
424  if (!marker->IsSmi()) {
425  // If we're using a "safe" stack iterator, we treat optimized
426  // frames as normal JavaScript frames to avoid having to look
427  // into the heap to determine the state. This is safe as long
428  // as nobody tries to GC...
429  if (!iterator->can_access_heap_objects_) return JAVA_SCRIPT;
430  Code::Kind kind = GetContainingCode(iterator->isolate(),
431  *(state->pc_address))->kind();
432  DCHECK(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
433  return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
434  }
435  return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
436 }
437 
438 
439 #ifdef DEBUG
440 bool StackFrame::can_access_heap_objects() const {
441  return iterator_->can_access_heap_objects_;
442 }
443 #endif
444 
445 
446 StackFrame::Type StackFrame::GetCallerState(State* state) const {
447  ComputeCallerState(state);
448  return ComputeType(iterator_, state);
449 }
450 
451 
452 Address StackFrame::UnpaddedFP() const {
453 #if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
454  if (!is_optimized()) return fp();
455  int32_t alignment_state = Memory::int32_at(
457 
458  return (alignment_state == kAlignmentPaddingPushed) ?
459  (fp() + kPointerSize) : fp();
460 #else
461  return fp();
462 #endif
463 }
464 
465 
467  return isolate()->heap()->js_entry_code();
468 }
469 
470 
472  GetCallerState(state);
473 }
474 
475 
477  const int offset = EntryFrameConstants::kCallerFPOffset;
478  Memory::Address_at(this->fp() + offset) = caller_fp;
479 }
480 
481 
483  const int offset = EntryFrameConstants::kCallerFPOffset;
484  Address fp = Memory::Address_at(this->fp() + offset);
485  return ExitFrame::GetStateForFramePointer(fp, state);
486 }
487 
488 
490  return isolate()->heap()->js_construct_entry_code();
491 }
492 
493 
495  const int offset = ExitFrameConstants::kCodeOffset;
496  return Memory::Object_at(fp() + offset);
497 }
498 
499 
501  return reinterpret_cast<Code*>(code_slot());
502 }
503 
504 
506  // Set up the caller state.
507  state->sp = caller_sp();
509  state->pc_address = ResolveReturnAddressLocation(
510  reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
511  if (FLAG_enable_ool_constant_pool) {
512  state->constant_pool_address = reinterpret_cast<Address*>(
514  }
515 }
516 
517 
520 }
521 
522 
524  // The arguments are traversed as part of the expression stack of
525  // the calling frame.
526  IteratePc(v, pc_address(), LookupCode());
527  v->VisitPointer(&code_slot());
528  if (FLAG_enable_ool_constant_pool) {
529  v->VisitPointer(&constant_pool_slot());
530  }
531 }
532 
533 
536 }
537 
538 
540  if (fp == 0) return NONE;
542  FillState(fp, sp, state);
543  DCHECK(*state->pc_address != NULL);
544  return EXIT;
545 }
546 
547 
550 }
551 
552 
554  state->sp = sp;
555  state->fp = fp;
556  state->pc_address = ResolveReturnAddressLocation(
557  reinterpret_cast<Address*>(sp - 1 * kPCOnStackSize));
558  state->constant_pool_address =
559  reinterpret_cast<Address*>(fp + ExitFrameConstants::kConstantPoolOffset);
560 }
561 
562 
565  return fp() + offset - n * kPointerSize;
566 }
567 
568 
570  return Memory::Object_at(GetExpressionAddress(fp, index));
571 }
572 
573 
576  return fp + offset - n * kPointerSize;
577 }
578 
579 
581  const int offset =
583  Address base = fp() + offset;
584  Address limit = sp();
585  DCHECK(base >= limit); // stack grows downwards
586  // Include register-allocated locals in number of expressions.
587  return static_cast<int>((base - limit) / kPointerSize);
588 }
589 
590 
592  state->sp = caller_sp();
593  state->fp = caller_fp();
594  state->pc_address = ResolveReturnAddressLocation(
595  reinterpret_cast<Address*>(ComputePCAddress(fp())));
596  state->constant_pool_address =
597  reinterpret_cast<Address*>(ComputeConstantPoolAddress(fp()));
598 }
599 
600 
603  caller_fp;
604 }
605 
606 
608  Address address = GetExpressionAddress(n);
609  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
610  if (it.handler()->includes(address)) return true;
611  }
612  return false;
613 }
614 
615 
617  // Make sure that we're not doing "safe" stack frame iteration. We cannot
618  // possibly find pointers in optimized frames in that state.
619  DCHECK(can_access_heap_objects());
620 
621  // Compute the safepoint information.
622  unsigned stack_slots = 0;
623  SafepointEntry safepoint_entry;
624  Code* code = StackFrame::GetSafepointData(
625  isolate(), pc(), &safepoint_entry, &stack_slots);
626  unsigned slot_space = stack_slots * kPointerSize;
627 
628  // Visit the outgoing parameters.
629  Object** parameters_base = &Memory::Object_at(sp());
630  Object** parameters_limit = &Memory::Object_at(
632 
633  // Visit the parameters that may be on top of the saved registers.
634  if (safepoint_entry.argument_count() > 0) {
635  v->VisitPointers(parameters_base,
636  parameters_base + safepoint_entry.argument_count());
637  parameters_base += safepoint_entry.argument_count();
638  }
639 
640  // Skip saved double registers.
641  if (safepoint_entry.has_doubles()) {
642  // Number of doubles not known at snapshot time.
643  DCHECK(!isolate()->serializer_enabled());
644  parameters_base += DoubleRegister::NumAllocatableRegisters() *
646  }
647 
648  // Visit the registers that contain pointers if any.
649  if (safepoint_entry.HasRegisters()) {
650  for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
651  if (safepoint_entry.HasRegisterAt(i)) {
652  int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
653  v->VisitPointer(parameters_base + reg_stack_index);
654  }
655  }
656  // Skip the words containing the register values.
657  parameters_base += kNumSafepointRegisters;
658  }
659 
660  // We're done dealing with the register bits.
661  uint8_t* safepoint_bits = safepoint_entry.bits();
662  safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
663 
664  // Visit the rest of the parameters.
665  v->VisitPointers(parameters_base, parameters_limit);
666 
667  // Visit pointer spill slots and locals.
668  for (unsigned index = 0; index < stack_slots; index++) {
669  int byte_index = index >> kBitsPerByteLog2;
670  int bit_index = index & (kBitsPerByte - 1);
671  if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
672  v->VisitPointer(parameters_limit + index);
673  }
674  }
675 
676  // Visit the return address in the callee and incoming arguments.
677  IteratePc(v, pc_address(), code);
678 
679  // Visit the context in stub frame and JavaScript frame.
680  // Visit the function in JavaScript frame.
681  Object** fixed_base = &Memory::Object_at(
683  Object** fixed_limit = &Memory::Object_at(fp());
684  v->VisitPointers(fixed_base, fixed_limit);
685 }
686 
687 
690 }
691 
692 
694  return static_cast<Code*>(isolate()->FindCodeObject(pc()));
695 }
696 
697 
700 }
701 
702 
704  return 0;
705 }
706 
707 
709 #ifdef DEBUG
710  // Make sure that optimized frames do not contain any stack handlers.
711  StackHandlerIterator it(this, top_handler());
712  DCHECK(it.done());
713 #endif
714 
716 }
717 
718 
719 void JavaScriptFrame::SetParameterValue(int index, Object* value) const {
720  Memory::Object_at(GetParameterSlot(index)) = value;
721 }
722 
723 
725  Address fp = caller_fp();
726  if (has_adapted_arguments()) {
727  // Skip the arguments adaptor frame and look at the real caller.
729  }
730  return IsConstructFrame(fp);
731 }
732 
733 
735  // If there is an arguments adaptor frame get the arguments length from it.
736  if (has_adapted_arguments()) {
737  return Smi::cast(GetExpression(caller_fp(), 0))->value();
738  } else {
740  }
741 }
742 
743 
745  return function()->code();
746 }
747 
748 
750  DCHECK(can_access_heap_objects() &&
751  isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
752 
753  return function()->shared()->formal_parameter_count();
754 }
755 
756 
759 }
760 
761 
763  DCHECK(functions->length() == 0);
764  functions->Add(function());
765 }
766 
767 
769  DCHECK(functions->length() == 0);
770  Code* code_pointer = LookupCode();
771  int offset = static_cast<int>(pc() - code_pointer->address());
772  FrameSummary summary(receiver(),
773  function(),
774  code_pointer,
775  offset,
776  IsConstructor());
777  functions->Add(summary);
778 }
779 
780 
782  Address pc, FILE* file,
783  bool print_line_number) {
784  PrintF(file, "%s", function->IsOptimized() ? "*" : "~");
785  function->PrintName(file);
786  int code_offset = static_cast<int>(pc - code->instruction_start());
787  PrintF(file, "+%d", code_offset);
788  if (print_line_number) {
789  SharedFunctionInfo* shared = function->shared();
790  int source_pos = code->SourcePosition(pc);
791  Object* maybe_script = shared->script();
792  if (maybe_script->IsScript()) {
793  Script* script = Script::cast(maybe_script);
794  int line = script->GetLineNumber(source_pos) + 1;
795  Object* script_name_raw = script->name();
796  if (script_name_raw->IsString()) {
797  String* script_name = String::cast(script->name());
798  SmartArrayPointer<char> c_script_name =
800  PrintF(file, " at %s:%d", c_script_name.get(), line);
801  } else {
802  PrintF(file, " at <unknown>:%d", line);
803  }
804  } else {
805  PrintF(file, " at <unknown>:<unknown>");
806  }
807  }
808 }
809 
810 
811 void JavaScriptFrame::PrintTop(Isolate* isolate, FILE* file, bool print_args,
812  bool print_line_number) {
813  // constructor calls
814  DisallowHeapAllocation no_allocation;
815  JavaScriptFrameIterator it(isolate);
816  while (!it.done()) {
817  if (it.frame()->is_java_script()) {
818  JavaScriptFrame* frame = it.frame();
819  if (frame->IsConstructor()) PrintF(file, "new ");
821  frame->pc(), file, print_line_number);
822  if (print_args) {
823  // function arguments
824  // (we are intentionally only printing the actually
825  // supplied parameters, not all parameters required)
826  PrintF(file, "(this=");
827  frame->receiver()->ShortPrint(file);
828  const int length = frame->ComputeParametersCount();
829  for (int i = 0; i < length; i++) {
830  PrintF(file, ", ");
831  frame->GetParameter(i)->ShortPrint(file);
832  }
833  PrintF(file, ")");
834  }
835  break;
836  }
837  it.Advance();
838  }
839 }
840 
841 
843  int* stack_handler_index) const {
844  int operands_count = store->length();
845  DCHECK_LE(operands_count, ComputeOperandsCount());
846 
847  // Visit the stack in LIFO order, saving operands and stack handlers into the
848  // array. The saved stack handlers store a link to the next stack handler,
849  // which will allow RestoreOperandStack to rewind the handlers.
850  StackHandlerIterator it(this, top_handler());
851  int i = operands_count - 1;
852  *stack_handler_index = -1;
853  for (; !it.done(); it.Advance()) {
854  StackHandler* handler = it.handler();
855  // Save operands pushed after the handler was pushed.
856  for (; GetOperandSlot(i) < handler->address(); i--) {
857  store->set(i, GetOperand(i));
858  }
860  DCHECK_EQ(handler->address(), GetOperandSlot(i));
861  int next_stack_handler_index = i + 1 - StackHandlerConstants::kSlotCount;
862  handler->Unwind(isolate(), store, next_stack_handler_index,
863  *stack_handler_index);
864  *stack_handler_index = next_stack_handler_index;
866  }
867 
868  // Save any remaining operands.
869  for (; i >= 0; i--) {
870  store->set(i, GetOperand(i));
871  }
872 }
873 
874 
876  int stack_handler_index) {
877  int operands_count = store->length();
878  DCHECK_LE(operands_count, ComputeOperandsCount());
879  int i = 0;
880  while (i <= stack_handler_index) {
881  if (i < stack_handler_index) {
882  // An operand.
883  DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
884  Memory::Object_at(GetOperandSlot(i)) = store->get(i);
885  i++;
886  } else {
887  // A stack handler.
888  DCHECK_EQ(i, stack_handler_index);
889  // The FixedArray store grows up. The stack grows down. So the operand
890  // slot for i actually points to the bottom of the top word in the
891  // handler. The base of the StackHandler* is the address of the bottom
892  // word, which will be the last slot that is in the handler.
893  int handler_slot_index = i + StackHandlerConstants::kSlotCount - 1;
894  StackHandler *handler =
895  StackHandler::FromAddress(GetOperandSlot(handler_slot_index));
896  stack_handler_index = handler->Rewind(isolate(), store, i, fp());
898  }
899  }
900 
901  for (; i < operands_count; i++) {
902  DCHECK_EQ(GetOperand(i), isolate()->heap()->the_hole_value());
903  Memory::Object_at(GetOperandSlot(i)) = store->get(i);
904  }
905 }
906 
907 
908 void FrameSummary::Print() {
909  PrintF("receiver: ");
910  receiver_->ShortPrint();
911  PrintF("\nfunction: ");
912  function_->shared()->DebugName()->ShortPrint();
913  PrintF("\ncode: ");
914  code_->ShortPrint();
915  if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
916  if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
917  PrintF("\npc: %d\n", offset_);
918 }
919 
920 
922  int literal_id) {
923  if (literal_id == Translation::kSelfLiteralId) {
924  return function();
925  }
926 
927  return JSFunction::cast(literal_array->get(literal_id));
928 }
929 
930 
932  DCHECK(frames->length() == 0);
933  DCHECK(is_optimized());
934 
935  // Delegate to JS frame in absence of turbofan deoptimization.
936  // TODO(turbofan): Revisit once we support deoptimization across the board.
937  if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
938  return JavaScriptFrame::Summarize(frames);
939  }
940 
941  int deopt_index = Safepoint::kNoDeoptimizationIndex;
942  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
943  FixedArray* literal_array = data->LiteralArray();
944 
945  // BUG(3243555): Since we don't have a lazy-deopt registered at
946  // throw-statements, we can't use the translation at the call-site of
947  // throw. An entry with no deoptimization index indicates a call-site
948  // without a lazy-deopt. As a consequence we are not allowed to inline
949  // functions containing throw.
950  DCHECK(deopt_index != Safepoint::kNoDeoptimizationIndex);
951 
952  TranslationIterator it(data->TranslationByteArray(),
953  data->TranslationIndex(deopt_index)->value());
954  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
955  DCHECK(opcode == Translation::BEGIN);
956  it.Next(); // Drop frame count.
957  int jsframe_count = it.Next();
958 
959  // We create the summary in reverse order because the frames
960  // in the deoptimization translation are ordered bottom-to-top.
961  bool is_constructor = IsConstructor();
962  int i = jsframe_count;
963  while (i > 0) {
964  opcode = static_cast<Translation::Opcode>(it.Next());
965  if (opcode == Translation::JS_FRAME) {
966  i--;
967  BailoutId ast_id = BailoutId(it.Next());
968  JSFunction* function = LiteralAt(literal_array, it.Next());
969  it.Next(); // Skip height.
970 
971  // The translation commands are ordered and the receiver is always
972  // at the first position.
973  // If we are at a call, the receiver is always in a stack slot.
974  // Otherwise we are not guaranteed to get the receiver value.
975  opcode = static_cast<Translation::Opcode>(it.Next());
976  int index = it.Next();
977 
978  // Get the correct receiver in the optimized frame.
979  Object* receiver = NULL;
980  if (opcode == Translation::LITERAL) {
981  receiver = data->LiteralArray()->get(index);
982  } else if (opcode == Translation::STACK_SLOT) {
983  // Positive index means the value is spilled to the locals
984  // area. Negative means it is stored in the incoming parameter
985  // area.
986  if (index >= 0) {
987  receiver = GetExpression(index);
988  } else {
989  // Index -1 overlaps with last parameter, -n with the first parameter,
990  // (-n - 1) with the receiver with n being the number of parameters
991  // of the outermost, optimized frame.
992  int parameter_count = ComputeParametersCount();
993  int parameter_index = index + parameter_count;
994  receiver = (parameter_index == -1)
995  ? this->receiver()
996  : this->GetParameter(parameter_index);
997  }
998  } else {
999  // The receiver is not in a stack slot nor in a literal. We give up.
1000  // TODO(3029): Materializing a captured object (or duplicated
1001  // object) is hard, we return undefined for now. This breaks the
1002  // produced stack trace, as constructor frames aren't marked as
1003  // such anymore.
1004  receiver = isolate()->heap()->undefined_value();
1005  }
1006 
1007  Code* code = function->shared()->code();
1008  DeoptimizationOutputData* output_data =
1009  DeoptimizationOutputData::cast(code->deoptimization_data());
1010  unsigned entry = Deoptimizer::GetOutputInfo(output_data,
1011  ast_id,
1012  function->shared());
1013  unsigned pc_offset =
1015  DCHECK(pc_offset > 0);
1016 
1017  FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
1018  frames->Add(summary);
1019  is_constructor = false;
1020  } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) {
1021  // The next encountered JS_FRAME will be marked as a constructor call.
1022  it.Skip(Translation::NumberOfOperandsFor(opcode));
1023  DCHECK(!is_constructor);
1024  is_constructor = true;
1025  } else {
1026  // Skip over operands to advance to the next opcode.
1027  it.Skip(Translation::NumberOfOperandsFor(opcode));
1028  }
1029  }
1030  DCHECK(!is_constructor);
1031 }
1032 
1033 
1035  int* deopt_index) {
1036  DCHECK(is_optimized());
1037 
1038  JSFunction* opt_function = function();
1039  Code* code = opt_function->code();
1040 
1041  // The code object may have been replaced by lazy deoptimization. Fall
1042  // back to a slow search in this case to find the original optimized
1043  // code object.
1044  if (!code->contains(pc())) {
1045  code = isolate()->inner_pointer_to_code_cache()->
1046  GcSafeFindCodeForInnerPointer(pc());
1047  }
1048  DCHECK(code != NULL);
1049  DCHECK(code->kind() == Code::OPTIMIZED_FUNCTION);
1050 
1051  SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
1052  *deopt_index = safepoint_entry.deoptimization_index();
1053  DCHECK(*deopt_index != Safepoint::kNoDeoptimizationIndex);
1054 
1055  return DeoptimizationInputData::cast(code->deoptimization_data());
1056 }
1057 
1058 
1060  DCHECK(is_optimized());
1061 
1062  // Delegate to JS frame in absence of turbofan deoptimization.
1063  // TODO(turbofan): Revisit once we support deoptimization across the board.
1064  if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
1066  }
1067 
1068  int deopt_index = Safepoint::kNoDeoptimizationIndex;
1069  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
1070 
1071  TranslationIterator it(data->TranslationByteArray(),
1072  data->TranslationIndex(deopt_index)->value());
1073  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
1074  DCHECK(opcode == Translation::BEGIN);
1075  USE(opcode);
1076  it.Next(); // Drop frame count.
1077  int jsframe_count = it.Next();
1078  return jsframe_count;
1079 }
1080 
1081 
1083  DCHECK(functions->length() == 0);
1084  DCHECK(is_optimized());
1085 
1086  // Delegate to JS frame in absence of turbofan deoptimization.
1087  // TODO(turbofan): Revisit once we support deoptimization across the board.
1088  if (LookupCode()->is_turbofanned() && !FLAG_turbo_deoptimization) {
1089  return JavaScriptFrame::GetFunctions(functions);
1090  }
1091 
1092  int deopt_index = Safepoint::kNoDeoptimizationIndex;
1093  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
1094  FixedArray* literal_array = data->LiteralArray();
1095 
1096  TranslationIterator it(data->TranslationByteArray(),
1097  data->TranslationIndex(deopt_index)->value());
1098  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
1099  DCHECK(opcode == Translation::BEGIN);
1100  it.Next(); // Drop frame count.
1101  int jsframe_count = it.Next();
1102 
1103  // We insert the frames in reverse order because the frames
1104  // in the deoptimization translation are ordered bottom-to-top.
1105  while (jsframe_count > 0) {
1106  opcode = static_cast<Translation::Opcode>(it.Next());
1107  if (opcode == Translation::JS_FRAME) {
1108  jsframe_count--;
1109  it.Next(); // Skip ast id.
1110  JSFunction* function = LiteralAt(literal_array, it.Next());
1111  it.Next(); // Skip height.
1112  functions->Add(function);
1113  } else {
1114  // Skip over operands to advance to the next opcode.
1115  it.Skip(Translation::NumberOfOperandsFor(opcode));
1116  }
1117  }
1118 }
1119 
1120 
1122  return Smi::cast(GetExpression(0))->value();
1123 }
1124 
1125 
1128 }
1129 
1130 
1132  // Internal frames have no arguments. The stack pointer of the
1133  // caller is at a fixed offset from the frame pointer.
1135 }
1136 
1137 
1139  return isolate()->builtins()->builtin(
1140  Builtins::kArgumentsAdaptorTrampoline);
1141 }
1142 
1143 
1145  const int offset = InternalFrameConstants::kCodeOffset;
1146  Object* code = Memory::Object_at(fp() + offset);
1147  DCHECK(code != NULL);
1148  return reinterpret_cast<Code*>(code);
1149 }
1150 
1151 
1152 void StackFrame::PrintIndex(StringStream* accumulator,
1153  PrintMode mode,
1154  int index) {
1155  accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1156 }
1157 
1158 
1159 void JavaScriptFrame::Print(StringStream* accumulator,
1160  PrintMode mode,
1161  int index) const {
1162  DisallowHeapAllocation no_gc;
1163  Object* receiver = this->receiver();
1164  JSFunction* function = this->function();
1165 
1166  accumulator->PrintSecurityTokenIfChanged(function);
1167  PrintIndex(accumulator, mode, index);
1168  Code* code = NULL;
1169  if (IsConstructor()) accumulator->Add("new ");
1170  accumulator->PrintFunction(function, receiver, &code);
1171 
1172  // Get scope information for nicer output, if possible. If code is NULL, or
1173  // doesn't contain scope info, scope_info will return 0 for the number of
1174  // parameters, stack local variables, context local variables, stack slots,
1175  // or context slots.
1176  SharedFunctionInfo* shared = function->shared();
1177  ScopeInfo* scope_info = shared->scope_info();
1178  Object* script_obj = shared->script();
1179  if (script_obj->IsScript()) {
1180  Script* script = Script::cast(script_obj);
1181  accumulator->Add(" [");
1182  accumulator->PrintName(script->name());
1183 
1184  Address pc = this->pc();
1185  if (code != NULL && code->kind() == Code::FUNCTION &&
1186  pc >= code->instruction_start() && pc < code->instruction_end()) {
1187  int source_pos = code->SourcePosition(pc);
1188  int line = script->GetLineNumber(source_pos) + 1;
1189  accumulator->Add(":%d", line);
1190  } else {
1191  int function_start_pos = shared->start_position();
1192  int line = script->GetLineNumber(function_start_pos) + 1;
1193  accumulator->Add(":~%d", line);
1194  }
1195 
1196  accumulator->Add("] ");
1197  }
1198 
1199  accumulator->Add("(this=%o", receiver);
1200 
1201  // Print the parameters.
1202  int parameters_count = ComputeParametersCount();
1203  for (int i = 0; i < parameters_count; i++) {
1204  accumulator->Add(",");
1205  // If we have a name for the parameter we print it. Nameless
1206  // parameters are either because we have more actual parameters
1207  // than formal parameters or because we have no scope information.
1208  if (i < scope_info->ParameterCount()) {
1209  accumulator->PrintName(scope_info->ParameterName(i));
1210  accumulator->Add("=");
1211  }
1212  accumulator->Add("%o", GetParameter(i));
1213  }
1214 
1215  accumulator->Add(")");
1216  if (mode == OVERVIEW) {
1217  accumulator->Add("\n");
1218  return;
1219  }
1220  if (is_optimized()) {
1221  accumulator->Add(" {\n// optimized frame\n}\n");
1222  return;
1223  }
1224  accumulator->Add(" {\n");
1225 
1226  // Compute the number of locals and expression stack elements.
1227  int stack_locals_count = scope_info->StackLocalCount();
1228  int heap_locals_count = scope_info->ContextLocalCount();
1229  int expressions_count = ComputeExpressionsCount();
1230 
1231  // Print stack-allocated local variables.
1232  if (stack_locals_count > 0) {
1233  accumulator->Add(" // stack-allocated locals\n");
1234  }
1235  for (int i = 0; i < stack_locals_count; i++) {
1236  accumulator->Add(" var ");
1237  accumulator->PrintName(scope_info->StackLocalName(i));
1238  accumulator->Add(" = ");
1239  if (i < expressions_count) {
1240  accumulator->Add("%o", GetExpression(i));
1241  } else {
1242  accumulator->Add("// no expression found - inconsistent frame?");
1243  }
1244  accumulator->Add("\n");
1245  }
1246 
1247  // Try to get hold of the context of this frame.
1248  Context* context = NULL;
1249  if (this->context() != NULL && this->context()->IsContext()) {
1250  context = Context::cast(this->context());
1251  }
1252  while (context->IsWithContext()) {
1253  context = context->previous();
1254  DCHECK(context != NULL);
1255  }
1256 
1257  // Print heap-allocated local variables.
1258  if (heap_locals_count > 0) {
1259  accumulator->Add(" // heap-allocated locals\n");
1260  }
1261  for (int i = 0; i < heap_locals_count; i++) {
1262  accumulator->Add(" var ");
1263  accumulator->PrintName(scope_info->ContextLocalName(i));
1264  accumulator->Add(" = ");
1265  if (context != NULL) {
1266  int index = Context::MIN_CONTEXT_SLOTS + i;
1267  if (index < context->length()) {
1268  accumulator->Add("%o", context->get(index));
1269  } else {
1270  accumulator->Add(
1271  "// warning: missing context slot - inconsistent frame?");
1272  }
1273  } else {
1274  accumulator->Add("// warning: no context found - inconsistent frame?");
1275  }
1276  accumulator->Add("\n");
1277  }
1278 
1279  // Print the expression stack.
1280  int expressions_start = stack_locals_count;
1281  if (expressions_start < expressions_count) {
1282  accumulator->Add(" // expression stack (top to bottom)\n");
1283  }
1284  for (int i = expressions_count - 1; i >= expressions_start; i--) {
1285  if (IsExpressionInsideHandler(i)) continue;
1286  accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1287  }
1288 
1289  // Print details about the function.
1290  if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1291  OStringStream os;
1292  SharedFunctionInfo* shared = function->shared();
1293  os << "--------- s o u r c e c o d e ---------\n"
1294  << SourceCodeOf(shared, FLAG_max_stack_trace_source_length)
1295  << "\n-----------------------------------------\n";
1296  accumulator->Add(os.c_str());
1297  }
1298 
1299  accumulator->Add("}\n\n");
1300 }
1301 
1302 
1303 void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1304  PrintMode mode,
1305  int index) const {
1306  int actual = ComputeParametersCount();
1307  int expected = -1;
1308  JSFunction* function = this->function();
1309  expected = function->shared()->formal_parameter_count();
1310 
1311  PrintIndex(accumulator, mode, index);
1312  accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1313  if (mode == OVERVIEW) {
1314  accumulator->Add("\n");
1315  return;
1316  }
1317  accumulator->Add(" {\n");
1318 
1319  // Print actual arguments.
1320  if (actual > 0) accumulator->Add(" // actual arguments\n");
1321  for (int i = 0; i < actual; i++) {
1322  accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1323  if (expected != -1 && i >= expected) {
1324  accumulator->Add(" // not passed to callee");
1325  }
1326  accumulator->Add("\n");
1327  }
1328 
1329  accumulator->Add("}\n\n");
1330 }
1331 
1332 
1334  StackHandlerIterator it(this, top_handler());
1335  DCHECK(!it.done());
1336  StackHandler* handler = it.handler();
1337  DCHECK(handler->is_js_entry());
1338  handler->Iterate(v, LookupCode());
1339 #ifdef DEBUG
1340  // Make sure that the entry frame does not contain more than one
1341  // stack handler.
1342  it.Advance();
1343  DCHECK(it.done());
1344 #endif
1345  IteratePc(v, pc_address(), LookupCode());
1346 }
1347 
1348 
1350  const int offset = StandardFrameConstants::kLastObjectOffset;
1351  Object** base = &Memory::Object_at(sp());
1352  Object** limit = &Memory::Object_at(fp() + offset) + 1;
1353  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1354  StackHandler* handler = it.handler();
1355  // Traverse pointers down to - but not including - the next
1356  // handler in the handler chain. Update the base to skip the
1357  // handler and allow the handler to traverse its own pointers.
1358  const Address address = handler->address();
1359  v->VisitPointers(base, reinterpret_cast<Object**>(address));
1360  base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1361  // Traverse the pointers in the handler itself.
1362  handler->Iterate(v, LookupCode());
1363  }
1364  v->VisitPointers(base, limit);
1365 }
1366 
1367 
1369  IterateExpressions(v);
1370  IteratePc(v, pc_address(), LookupCode());
1371 }
1372 
1373 
1375  // Internal frames only have object pointers on the expression stack
1376  // as they never have any arguments.
1377  IterateExpressions(v);
1378  IteratePc(v, pc_address(), LookupCode());
1379 }
1380 
1381 
1383  Object** base = &Memory::Object_at(sp());
1384  Object** limit = &Memory::Object_at(fp() +
1386  v->VisitPointers(base, limit);
1388  const int offset = StandardFrameConstants::kLastObjectOffset;
1389  limit = &Memory::Object_at(fp() + offset) + 1;
1390  v->VisitPointers(base, limit);
1391  IteratePc(v, pc_address(), LookupCode());
1392 }
1393 
1394 
1397 }
1398 
1399 
1401  Code* trampoline;
1403  FindCodeInCache(&trampoline);
1404  if (trampoline->contains(pc())) {
1405  return trampoline;
1406  }
1407 
1409  FindCodeInCache(&trampoline);
1410  if (trampoline->contains(pc())) {
1411  return trampoline;
1412  }
1413 
1414  UNREACHABLE();
1415  return NULL;
1416 }
1417 
1418 
1419 // -------------------------------------------------------------------------
1420 
1421 
1422 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
1423  DCHECK(n >= 0);
1424  for (int i = 0; i <= n; i++) {
1425  while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1426  if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1427  iterator_.Advance();
1428  }
1429  UNREACHABLE();
1430  return NULL;
1431 }
1432 
1433 
1434 // -------------------------------------------------------------------------
1435 
1436 
1438  MapWord map_word = object->map_word();
1439  return map_word.IsForwardingAddress() ?
1440  map_word.ToForwardingAddress()->map() : map_word.ToMap();
1441 }
1442 
1443 
1445  return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1446 }
1447 
1448 
1449 #ifdef DEBUG
1450 static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1451  Map* map = GcSafeMapOfCodeSpaceObject(code);
1452  DCHECK(map == code->GetHeap()->code_map());
1453  Address start = code->address();
1454  Address end = code->address() + code->SizeFromMap(map);
1455  return start <= addr && addr < end;
1456 }
1457 #endif
1458 
1459 
1461  Address inner_pointer) {
1462  Code* code = reinterpret_cast<Code*>(object);
1463  DCHECK(code != NULL && GcSafeCodeContains(code, inner_pointer));
1464  return code;
1465 }
1466 
1467 
1469  Address inner_pointer) {
1470  Heap* heap = isolate_->heap();
1471  // Check if the inner pointer points into a large object chunk.
1472  LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1473  if (large_page != NULL) {
1474  return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1475  }
1476 
1477  // Iterate through the page until we reach the end or find an object starting
1478  // after the inner pointer.
1479  Page* page = Page::FromAddress(inner_pointer);
1480 
1481  Address addr = page->skip_list()->StartFor(inner_pointer);
1482 
1483  Address top = heap->code_space()->top();
1484  Address limit = heap->code_space()->limit();
1485 
1486  while (true) {
1487  if (addr == top && addr != limit) {
1488  addr = limit;
1489  continue;
1490  }
1491 
1492  HeapObject* obj = HeapObject::FromAddress(addr);
1493  int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1494  Address next_addr = addr + obj_size;
1495  if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1496  addr = next_addr;
1497  }
1498 }
1499 
1500 
1503  isolate_->counters()->pc_to_code()->Increment();
1506  static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)),
1508  uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1509  InnerPointerToCodeCacheEntry* entry = cache(index);
1510  if (entry->inner_pointer == inner_pointer) {
1511  isolate_->counters()->pc_to_code_cached()->Increment();
1512  DCHECK(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
1513  } else {
1514  // Because this code may be interrupted by a profiling signal that
1515  // also queries the cache, we cannot update inner_pointer before the code
1516  // has been set. Otherwise, we risk trying to use a cache entry before
1517  // the code has been computed.
1518  entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
1519  entry->safepoint_entry.Reset();
1520  entry->inner_pointer = inner_pointer;
1521  }
1522  return entry;
1523 }
1524 
1525 
1526 // -------------------------------------------------------------------------
1527 
1528 
1529 void StackHandler::Unwind(Isolate* isolate,
1530  FixedArray* array,
1531  int offset,
1532  int previous_handler_offset) const {
1534  DCHECK_LE(0, offset);
1536  // Unwinding a stack handler into an array chains it in the opposite
1537  // direction, re-using the "next" slot as a "previous" link, so that stack
1538  // handlers can be later re-wound in the correct order. Decode the "state"
1539  // slot into "index" and "kind" and store them separately, using the fp slot.
1540  array->set(offset, Smi::FromInt(previous_handler_offset)); // next
1541  array->set(offset + 1, *code_address()); // code
1542  array->set(offset + 2, Smi::FromInt(static_cast<int>(index()))); // state
1543  array->set(offset + 3, *context_address()); // context
1544  array->set(offset + 4, Smi::FromInt(static_cast<int>(kind()))); // fp
1545 
1546  *isolate->handler_address() = next()->address();
1547 }
1548 
1549 
1550 int StackHandler::Rewind(Isolate* isolate,
1551  FixedArray* array,
1552  int offset,
1553  Address fp) {
1555  DCHECK_LE(0, offset);
1556  DCHECK_GE(array->length(), offset + StackHandlerConstants::kSlotCount);
1557  Smi* prev_handler_offset = Smi::cast(array->get(offset));
1558  Code* code = Code::cast(array->get(offset + 1));
1559  Smi* smi_index = Smi::cast(array->get(offset + 2));
1560  Object* context = array->get(offset + 3);
1561  Smi* smi_kind = Smi::cast(array->get(offset + 4));
1562 
1563  unsigned state = KindField::encode(static_cast<Kind>(smi_kind->value())) |
1564  IndexField::encode(static_cast<unsigned>(smi_index->value()));
1565 
1567  *isolate->handler_address();
1571  context;
1572  SetFp(address() + StackHandlerConstants::kFPOffset, fp);
1573 
1574  *isolate->handler_address() = address();
1575 
1576  return prev_handler_offset->value();
1577 }
1578 
1579 
1580 // -------------------------------------------------------------------------
1581 
1582 int NumRegs(RegList reglist) { return base::bits::CountPopulation32(reglist); }
1583 
1584 
1587 };
1588 
1590 
1592  int i = 0;
1593  for (int r = 0; r < kNumRegs; r++)
1594  if ((kJSCallerSaved & (1 << r)) != 0)
1596 
1598 }
1599 
1600 
1601 int JSCallerSavedCode(int n) {
1602  DCHECK(0 <= n && n < kNumJSCallerSaved);
1603  return caller_saved_code_data.reg_code[n];
1604 }
1605 
1606 
1607 #define DEFINE_WRAPPER(type, field) \
1608 class field##_Wrapper : public ZoneObject { \
1609  public: /* NOLINT */ \
1610  field##_Wrapper(const field& original) : frame_(original) { \
1611  } \
1612  field frame_; \
1613 };
1615 #undef DEFINE_WRAPPER
1616 
1618 #define FRAME_TYPE_CASE(type, field) \
1619  case StackFrame::type: { \
1620  field##_Wrapper* wrapper = \
1621  new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
1622  return &wrapper->frame_; \
1623  }
1624 
1625  switch (frame->type()) {
1627  default: UNREACHABLE();
1628  }
1629 #undef FRAME_TYPE_CASE
1630  return NULL;
1631 }
1632 
1633 
1635  ZoneList<StackFrame*> list(10, zone);
1636  for (StackFrameIterator it(isolate); !it.done(); it.Advance()) {
1637  StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1638  list.Add(frame, zone);
1639  }
1640  return list.ToVector();
1641 }
1642 
1643 
1644 } } // namespace v8::internal
#define BASE_EMBEDDED
Definition: allocation.h:45
Isolate represents an isolated instance of the V8 engine.
Definition: v8.h:4356
A JavaScript object (ECMA-262, 4.3.3)
Definition: v8.h:2283
A single JavaScript stack frame.
Definition: v8.h:1358
virtual int GetNumberOfIncomingArguments() const
Definition: frames.cc:1121
virtual Code * unchecked_code() const
Definition: frames.cc:1138
virtual Address GetCallerStackPointer() const
Definition: frames.cc:1126
virtual void Print(StringStream *accumulator, PrintMode mode, int index) const
Definition: frames.cc:1303
const Address limit_
Definition: frames.cc:47
StackHandler * handler() const
Definition: frames.cc:36
StackHandlerIterator(const StackFrame *frame, StackHandler *handler)
Definition: frames.cc:30
StackHandler * handler_
Definition: frames.cc:48
static T decode(U value)
Definition: utils.h:228
Code * builtin(Name name)
Definition: builtins.h:254
SafepointEntry GetSafepointEntry(Address pc)
Definition: objects.cc:10244
bool contains(byte *pc)
Definition: objects-inl.h:6211
byte * instruction_start()
Definition: objects-inl.h:6176
static const int kHeaderSize
Definition: objects.h:5373
int SourcePosition(Address pc)
Definition: objects.cc:10192
static Context * cast(Object *context)
Definition: contexts.h:255
static int GetOutputInfo(DeoptimizationOutputData *data, BailoutId node_id, SharedFunctionInfo *shared)
Definition: deoptimizer.cc:707
virtual Code * unchecked_code() const
Definition: frames.cc:489
static const int kCallerFPOffset
Definition: frames-arm.h:80
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:1333
virtual void SetCallerFp(Address caller_fp)
Definition: frames.cc:476
virtual void ComputeCallerState(State *state) const
Definition: frames.cc:471
virtual Code * unchecked_code() const
Definition: frames.cc:466
virtual Type GetCallerState(State *state) const
Definition: frames.cc:482
static const int kCallerSPDisplacement
Definition: frames-arm.h:102
static const int kCallerPCOffset
Definition: frames-arm.h:98
static const int kCodeOffset
Definition: frames-arm.h:92
static const int kConstantPoolOffset
Definition: frames-arm.h:90
static const int kCallerFPOffset
Definition: frames-arm.h:96
virtual void ComputeCallerState(State *state) const
Definition: frames.cc:505
static void FillState(Address fp, Address sp, State *state)
Definition: frames.cc:553
static Address ComputeStackPointer(Address fp)
Definition: frames.cc:548
virtual void SetCallerFp(Address caller_fp)
Definition: frames.cc:518
virtual Address GetCallerStackPointer() const
Definition: frames.cc:534
virtual Code * unchecked_code() const
Definition: frames.cc:500
Object *& constant_pool_slot() const
static Type GetStateForFramePointer(Address fp, State *state)
Definition: frames.cc:539
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:523
Object *& code_slot() const
Definition: frames.cc:494
Object * get(int index)
Definition: objects-inl.h:2165
void set(int index, Object *value)
Definition: objects-inl.h:2190
static HeapObject * FromAddress(Address address)
Definition: objects-inl.h:1464
MapWord map_word() const
Definition: objects-inl.h:1440
OldSpace * code_space()
Definition: heap.h:596
LargeObjectSpace * lo_space()
Definition: heap.h:600
Code * GcSafeFindCodeForInnerPointer(Address inner_pointer)
Definition: frames.cc:1468
InnerPointerToCodeCacheEntry * GetCacheEntry(Address inner_pointer)
Definition: frames.cc:1502
InnerPointerToCodeCacheEntry * cache(int index)
Definition: frames.h:58
Code * GcSafeCastToCode(HeapObject *object, Address inner_pointer)
Definition: frames.cc:1460
static const int kInnerPointerToCodeCacheSize
Definition: frames.h:62
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:1374
virtual Code * unchecked_code() const
Definition: frames.cc:1144
virtual Address GetCallerStackPointer() const
Definition: frames.cc:1131
static Address c_entry_fp(ThreadLocalTop *thread)
Definition: isolate.h:647
Object * FindCodeObject(Address a)
Definition: isolate.cc:2214
Builtins * builtins()
Definition: isolate.h:947
Counters * counters()
Definition: isolate.h:857
InnerPointerToCodeCache * inner_pointer_to_code_cache()
Definition: isolate.h:911
ThreadLocalTop * thread_local_top()
Definition: isolate.h:878
static Address handler(ThreadLocalTop *thread)
Definition: isolate.h:650
Address * handler_address()
Definition: isolate.h:655
static const int kDynamicAlignmentStateOffset
Definition: frames-ia32.h:78
virtual int GetNumberOfIncomingArguments() const
Definition: frames.cc:749
virtual int GetInlineCount()
Definition: frames.h:599
void SetParameterValue(int index, Object *value) const
Definition: frames.cc:719
void RestoreOperandStack(FixedArray *store, int stack_handler_index)
Definition: frames.cc:875
Object * receiver() const
Definition: frames-inl.h:250
bool IsConstructor() const
Definition: frames.cc:724
virtual void GetFunctions(List< JSFunction * > *functions)
Definition: frames.cc:762
bool has_adapted_arguments() const
Definition: frames-inl.h:260
static void PrintTop(Isolate *isolate, FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:811
Address GetParameterSlot(int index) const
Definition: frames-inl.h:209
virtual void Summarize(List< FrameSummary > *frames)
Definition: frames.cc:768
Address GetOperandSlot(int index) const
Definition: frames-inl.h:222
int GetArgumentsLength() const
Definition: frames.cc:734
virtual void Print(StringStream *accumulator, PrintMode mode, int index) const
Definition: frames.cc:1159
Object * GetParameter(int index) const
Definition: frames-inl.h:217
virtual Code * unchecked_code() const
Definition: frames.cc:744
Object * GetOperand(int index) const
Definition: frames-inl.h:233
static JavaScriptFrame * cast(StackFrame *frame)
Definition: frames.h:612
JSFunction * function() const
Definition: frames-inl.h:265
void SaveOperandStack(FixedArray *store, int *stack_handler_index) const
Definition: frames.cc:842
static void PrintFunctionAndOffset(JSFunction *function, Code *code, Address pc, FILE *file, bool print_line_number)
Definition: frames.cc:781
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:1368
int ComputeParametersCount() const
Definition: frames.h:562
virtual Address GetCallerStackPointer() const
Definition: frames.cc:757
LargePage * FindPage(Address a)
Definition: spaces.cc:2910
HeapObject * GetObject()
Definition: spaces.h:798
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:17
Vector< T > ToVector() const
Definition: list.h:81
static int SafepointRegisterStackIndex(int reg_code)
SkipList * skip_list()
Definition: spaces.h:613
static MemoryChunk * FromAddress(Address a)
Definition: spaces.h:276
static Object *& Object_at(Address addr)
Definition: v8memory.h:60
static Address & Address_at(Address addr)
Definition: v8memory.h:56
static uintptr_t & uintptr_at(Address addr)
Definition: v8memory.h:48
static int32_t & int32_at(Address addr)
Definition: v8memory.h:28
const char * c_str() const
Definition: ostreams.h:84
void ShortPrint(FILE *out=stdout)
Definition: objects.cc:905
DeoptimizationInputData * GetDeoptimizationData(int *deopt_index)
Definition: frames.cc:1034
virtual int GetInlineCount()
Definition: frames.cc:1059
virtual void Summarize(List< FrameSummary > *frames)
Definition: frames.cc:931
virtual void GetFunctions(List< JSFunction * > *functions)
Definition: frames.cc:1082
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:708
JSFunction * LiteralAt(FixedArray *literal_array, int literal_id)
Definition: frames.cc:921
StackFrame::Type top_frame_type_
Definition: frames.h:917
ExternalCallbackScope * external_callback_scope_
Definition: frames.h:918
bool IsValidTop(ThreadLocalTop *top) const
Definition: frames.cc:250
bool IsValidFrame(StackFrame *frame) const
Definition: frames.cc:284
bool IsValidStackAddress(Address addr) const
Definition: frames.h:907
bool IsValidCaller(StackFrame *frame)
Definition: frames.cc:289
bool IsValidExitFrame(Address fp) const
Definition: frames.cc:314
SafeStackFrameIterator(Isolate *isolate, Address fp, Address sp, Address js_entry_sp)
Definition: frames.cc:194
String * ContextLocalName(int var)
Definition: scopeinfo.cc:239
String * ParameterName(int var)
Definition: scopeinfo.cc:216
String * StackLocalName(int var)
Definition: scopeinfo.cc:232
static int GetLineNumber(Handle< Script > script, int code_pos)
Definition: objects.cc:9673
Address StartFor(Address addr)
Definition: spaces.h:958
static Smi * FromInt(int value)
Definition: objects-inl.h:1321
StackFrame * frame() const
Definition: frames.h:842
void Reset(ThreadLocalTop *top)
Definition: frames.cc:101
StackFrameIterator(Isolate *isolate)
Definition: frames.cc:66
static const int kFPOffset
Definition: frames.h:75
static const int kCodeOffset
Definition: frames.h:72
static const int kContextOffset
Definition: frames.h:74
static const int kNextOffset
Definition: frames.h:71
static const int kSlotCount
Definition: frames.h:78
static const int kStateOffset
Definition: frames.h:73
StackTraceFrameIterator(Isolate *isolate)
Definition: frames.cc:167
static const int kContextOffset
Definition: frames.h:162
static const int kExpressionsOffset
Definition: frames.h:160
static const int kCallerSPOffset
Definition: frames.h:167
static const int kLastObjectOffset
Definition: frames.h:169
static const int kMarkerOffset
Definition: frames.h:161
static const int kCallerFPOffset
Definition: frames.h:165
Object * context() const
Definition: frames-inl.h:164
Address GetExpressionAddress(int n) const
Definition: frames.cc:563
static Address ComputeConstantPoolAddress(Address fp)
Definition: frames-inl.h:185
static bool IsArgumentsAdaptorFrame(Address fp)
Definition: frames-inl.h:190
Address caller_fp() const
Definition: frames-inl.h:170
void IterateExpressions(ObjectVisitor *v) const
Definition: frames.cc:1349
void IterateCompiledFrame(ObjectVisitor *v) const
Definition: frames.cc:616
virtual void ComputeCallerState(State *state) const
Definition: frames.cc:591
bool IsExpressionInsideHandler(int n) const
Definition: frames.cc:607
Object * GetExpression(int index) const
Definition: frames-inl.h:154
virtual void SetCallerFp(Address caller_fp)
Definition: frames.cc:601
int ComputeExpressionsCount() const
Definition: frames.cc:580
static Address ComputePCAddress(Address fp)
Definition: frames-inl.h:180
static bool IsConstructFrame(Address fp)
Definition: frames-inl.h:197
SmartArrayPointer< char > ToCString(AllowNullsFlag allow_nulls, RobustnessFlag robustness_flag, int offset, int length, int *length_output=0)
Definition: objects.cc:8004
static const int kFirstRegisterParameterFrameOffset
Definition: frames.h:752
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:1382
virtual Address GetCallerStackPointer() const
Definition: frames.cc:1395
virtual Code * unchecked_code() const
Definition: frames.cc:1400
virtual int GetNumberOfIncomingArguments() const
Definition: frames.cc:703
virtual Address GetCallerStackPointer() const
Definition: frames.cc:698
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:688
virtual Code * unchecked_code() const
Definition: frames.cc:693
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf map
enable harmony numeric enable harmony object literal extensions true
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_BOOL(enable_always_align_csp
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi the new space consists of two semi spaces print one trace line following each garbage collection do not print trace line after scavenger collection print cumulative GC statistics in only print modified registers Trace simulator debug messages Implied by trace sim abort randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot A filename with extra code to be included in the A file to write the raw snapshot bytes A file to write the raw context snapshot bytes Write V8 startup blob file(mksnapshot only)") DEFINE_BOOL(profile_hydrogen_code_stub_compilation
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define DEFINE_WRAPPER(type, field)
Definition: frames.cc:1607
#define FRAME_TYPE_CASE(type, field)
#define INITIALIZE_SINGLETON(type, field)
Definition: frames.cc:55
#define STACK_FRAME_TYPE_LIST(V)
Definition: frames.h:136
#define UNREACHABLE()
Definition: logging.h:30
#define DCHECK_LE(v1, v2)
Definition: logging.h:210
#define DCHECK_GE(v1, v2)
Definition: logging.h:208
#define DCHECK(condition)
Definition: logging.h:205
#define DCHECK_EQ(v1, v2)
Definition: logging.h:206
void USE(T)
Definition: macros.h:322
int int32_t
Definition: unicode.cc:24
uint32_t CountPopulation32(uint32_t value)
Definition: bits.h:22
bool IsPowerOfTwo32(uint32_t value)
Definition: bits.h:77
const int kPointerSize
Definition: globals.h:129
JSCallerSavedCodeData caller_saved_code_data
Definition: frames.cc:1589
const int kAlignmentPaddingPushed
Definition: frames-ia32.h:32
const RegList kJSCallerSaved
Definition: frames-arm.h:24
@ ARGUMENTS_ADAPTOR
Definition: hydrogen.h:546
TypeImpl< ZoneTypeConfig > Type
const int kPCOnStackSize
Definition: globals.h:135
int JSCallerSavedCode(int n)
Definition: frames.cc:1601
const int kNumSafepointRegisters
Definition: frames-arm.h:67
const int kDoubleSize
Definition: globals.h:127
@ DISALLOW_NULLS
Definition: objects.h:8337
const Register fp
static const uint32_t kZeroHashSeed
Definition: utils.h:245
@ JS_FUNCTION_STUB_MODE
Definition: code-stubs.h:350
@ NOT_JS_FUNCTION_STUB_MODE
Definition: code-stubs.h:350
kSerializedDataOffset Object
Definition: objects-inl.h:5322
const Register sp
@ ROBUST_STRING_TRAVERSAL
Definition: objects.h:8338
const Register pc
int NumRegs(RegList reglist)
Definition: frames.cc:1582
const int kBitsPerByteLog2
Definition: globals.h:163
uint32_t RegList
Definition: frames.h:18
byte * Address
Definition: globals.h:101
void PrintF(const char *format,...)
Definition: utils.cc:80
Vector< StackFrame * > CreateStackMap(Isolate *isolate, Zone *zone)
Definition: frames.cc:1634
uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed)
Definition: utils.h:249
static StackFrame * AllocateFrameCopy(StackFrame *frame, Zone *zone)
Definition: frames.cc:1617
const int kNumJSCallerSaved
Definition: frames-arm.h:30
STATIC_ASSERT(sizeof(CPURegister)==sizeof(Register))
const int kBitsPerByte
Definition: globals.h:162
static int GcSafeSizeOfCodeSpaceObject(HeapObject *object)
Definition: frames.cc:1444
static Map * GcSafeMapOfCodeSpaceObject(HeapObject *object)
Definition: frames.cc:1437
void SetUpJSCallerSavedCodeData()
Definition: frames.cc:1591
const int kNumRegs
Definition: frames-arm.h:20
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20
uintptr_t(* ReturnAddressLocationResolver)(uintptr_t return_addr_location)
ReturnAddressLocationResolver is used as a callback function when v8 is resolving the location of a r...
Definition: v8.h:4936
@ NONE
int reg_code[kNumJSCallerSaved]
Definition: frames.cc:1586