v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
frames.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "ast.h"
31 #include "deoptimizer.h"
32 #include "frames-inl.h"
33 #include "full-codegen.h"
34 #include "lazy-instance.h"
35 #include "mark-compact.h"
36 #include "safepoint-table.h"
37 #include "scopeinfo.h"
38 #include "string-stream.h"
39 
40 #include "allocation-inl.h"
41 
42 namespace v8 {
43 namespace internal {
44 
45 
46 static ReturnAddressLocationResolver return_address_location_resolver = NULL;
47 
48 
49 // Resolves pc_address through the resolution address function if one is set.
50 static inline Address* ResolveReturnAddressLocation(Address* pc_address) {
51  if (return_address_location_resolver == NULL) {
52  return pc_address;
53  } else {
54  return reinterpret_cast<Address*>(
55  return_address_location_resolver(
56  reinterpret_cast<uintptr_t>(pc_address)));
57  }
58 }
59 
60 
61 // Iterator that supports traversing the stack handlers of a
62 // particular frame. Needs to know the top of the handler chain.
63 class StackHandlerIterator BASE_EMBEDDED {
64  public:
65  StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
66  : limit_(frame->fp()), handler_(handler) {
67  // Make sure the handler has already been unwound to this frame.
68  ASSERT(frame->sp() <= handler->address());
69  }
70 
71  StackHandler* handler() const { return handler_; }
72 
73  bool done() {
74  return handler_ == NULL || handler_->address() > limit_;
75  }
76  void Advance() {
77  ASSERT(!done());
78  handler_ = handler_->next();
79  }
80 
81  private:
82  const Address limit_;
83  StackHandler* handler_;
84 };
85 
86 
87 // -------------------------------------------------------------------------
88 
89 
90 #define INITIALIZE_SINGLETON(type, field) field##_(this),
91 StackFrameIterator::StackFrameIterator()
92  : isolate_(Isolate::Current()),
94  frame_(NULL), handler_(NULL),
95  thread_(isolate_->thread_local_top()),
96  fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
97  Reset();
98 }
99 StackFrameIterator::StackFrameIterator(Isolate* isolate)
100  : isolate_(isolate),
102  frame_(NULL), handler_(NULL),
103  thread_(isolate_->thread_local_top()),
104  fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
105  Reset();
106 }
107 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
108  : isolate_(isolate),
110  frame_(NULL), handler_(NULL), thread_(t),
111  fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
112  Reset();
113 }
114 StackFrameIterator::StackFrameIterator(Isolate* isolate,
115  bool use_top, Address fp, Address sp)
116  : isolate_(isolate),
118  frame_(NULL), handler_(NULL),
119  thread_(use_top ? isolate_->thread_local_top() : NULL),
120  fp_(use_top ? NULL : fp), sp_(sp),
121  advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
122  &StackFrameIterator::AdvanceWithoutHandler) {
123  if (use_top || fp != NULL) {
124  Reset();
125  }
126 }
127 
128 #undef INITIALIZE_SINGLETON
129 
130 
131 void StackFrameIterator::AdvanceWithHandler() {
132  ASSERT(!done());
133  // Compute the state of the calling frame before restoring
134  // callee-saved registers and unwinding handlers. This allows the
135  // frame code that computes the caller state to access the top
136  // handler and the value of any callee-saved register if needed.
137  StackFrame::State state;
138  StackFrame::Type type = frame_->GetCallerState(&state);
139 
140  // Unwind handlers corresponding to the current frame.
141  StackHandlerIterator it(frame_, handler_);
142  while (!it.done()) it.Advance();
143  handler_ = it.handler();
144 
145  // Advance to the calling frame.
146  frame_ = SingletonFor(type, &state);
147 
148  // When we're done iterating over the stack frames, the handler
149  // chain must have been completely unwound.
150  ASSERT(!done() || handler_ == NULL);
151 }
152 
153 
154 void StackFrameIterator::AdvanceWithoutHandler() {
155  // A simpler version of Advance which doesn't care about handler.
156  ASSERT(!done());
157  StackFrame::State state;
158  StackFrame::Type type = frame_->GetCallerState(&state);
159  frame_ = SingletonFor(type, &state);
160 }
161 
162 
163 void StackFrameIterator::Reset() {
164  StackFrame::State state;
165  StackFrame::Type type;
166  if (thread_ != NULL) {
167  type = ExitFrame::GetStateForFramePointer(
168  Isolate::c_entry_fp(thread_), &state);
169  handler_ = StackHandler::FromAddress(
170  Isolate::handler(thread_));
171  } else {
172  ASSERT(fp_ != NULL);
173  state.fp = fp_;
174  state.sp = sp_;
175  state.pc_address = ResolveReturnAddressLocation(
176  reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)));
177  type = StackFrame::ComputeType(isolate(), &state);
178  }
179  if (SingletonFor(type) == NULL) return;
180  frame_ = SingletonFor(type, &state);
181 }
182 
183 
184 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
185  StackFrame::State* state) {
186  if (type == StackFrame::NONE) return NULL;
187  StackFrame* result = SingletonFor(type);
188  ASSERT(result != NULL);
189  result->state_ = *state;
190  return result;
191 }
192 
193 
194 StackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
195 #define FRAME_TYPE_CASE(type, field) \
196  case StackFrame::type: result = &field##_; break;
197 
198  StackFrame* result = NULL;
199  switch (type) {
200  case StackFrame::NONE: return NULL;
202  default: break;
203  }
204  return result;
205 
206 #undef FRAME_TYPE_CASE
207 }
208 
209 
210 // -------------------------------------------------------------------------
211 
212 
213 StackTraceFrameIterator::StackTraceFrameIterator() {
214  if (!done() && !IsValidFrame()) Advance();
215 }
216 
217 
218 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
219  : JavaScriptFrameIterator(isolate) {
220  if (!done() && !IsValidFrame()) Advance();
221 }
222 
223 
225  while (true) {
226  JavaScriptFrameIterator::Advance();
227  if (done()) return;
228  if (IsValidFrame()) return;
229  }
230 }
231 
232 bool StackTraceFrameIterator::IsValidFrame() {
233  if (!frame()->function()->IsJSFunction()) return false;
234  Object* script = JSFunction::cast(frame()->function())->shared()->script();
235  // Don't show functions from native scripts to user.
236  return (script->IsScript() &&
237  Script::TYPE_NATIVE != Script::cast(script)->type()->value());
238 }
239 
240 
241 // -------------------------------------------------------------------------
242 
243 
244 bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
245  if (!validator_.IsValid(fp)) return false;
247  if (!validator_.IsValid(sp)) return false;
248  StackFrame::State state;
249  ExitFrame::FillState(fp, sp, &state);
250  if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
251  return false;
252  }
253  return *state.pc_address != NULL;
254 }
255 
256 
257 SafeStackFrameIterator::ActiveCountMaintainer::ActiveCountMaintainer(
258  Isolate* isolate)
259  : isolate_(isolate) {
260  isolate_->set_safe_stack_iterator_counter(
261  isolate_->safe_stack_iterator_counter() + 1);
262 }
263 
264 
265 SafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() {
266  isolate_->set_safe_stack_iterator_counter(
267  isolate_->safe_stack_iterator_counter() - 1);
268 }
269 
270 
271 SafeStackFrameIterator::SafeStackFrameIterator(
272  Isolate* isolate,
273  Address fp, Address sp, Address low_bound, Address high_bound) :
274  maintainer_(isolate),
275  stack_validator_(low_bound, high_bound),
276  is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
277  is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
278  is_working_iterator_(is_valid_top_ || is_valid_fp_),
279  iteration_done_(!is_working_iterator_),
280  iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
281 }
282 
283 bool SafeStackFrameIterator::is_active(Isolate* isolate) {
284  return isolate->safe_stack_iterator_counter() > 0;
285 }
286 
287 
288 bool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
289  Address low_bound, Address high_bound) {
290  ThreadLocalTop* top = isolate->thread_local_top();
291  Address fp = Isolate::c_entry_fp(top);
292  ExitFrameValidator validator(low_bound, high_bound);
293  if (!validator.IsValidFP(fp)) return false;
294  return Isolate::handler(top) != NULL;
295 }
296 
297 
298 void SafeStackFrameIterator::Advance() {
299  ASSERT(is_working_iterator_);
300  ASSERT(!done());
301  StackFrame* last_frame = iterator_.frame();
302  Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
303  // Before advancing to the next stack frame, perform pointer validity tests
304  iteration_done_ = !IsValidFrame(last_frame) ||
305  !CanIterateHandles(last_frame, iterator_.handler()) ||
306  !IsValidCaller(last_frame);
307  if (iteration_done_) return;
308 
309  iterator_.Advance();
310  if (iterator_.done()) return;
311  // Check that we have actually moved to the previous frame in the stack
312  StackFrame* prev_frame = iterator_.frame();
313  iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
314 }
315 
316 
317 bool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
318  StackHandler* handler) {
319  // If StackIterator iterates over StackHandles, verify that
320  // StackHandlerIterator can be instantiated (see StackHandlerIterator
321  // constructor.)
322  return !is_valid_top_ || (frame->sp() <= handler->address());
323 }
324 
325 
326 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
327  return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
328 }
329 
330 
331 bool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
332  StackFrame::State state;
333  if (frame->is_entry() || frame->is_entry_construct()) {
334  // See EntryFrame::GetCallerState. It computes the caller FP address
335  // and calls ExitFrame::GetStateForFramePointer on it. We need to be
336  // sure that caller FP address is valid.
337  Address caller_fp = Memory::Address_at(
339  ExitFrameValidator validator(stack_validator_);
340  if (!validator.IsValidFP(caller_fp)) return false;
341  } else if (frame->is_arguments_adaptor()) {
342  // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
343  // the number of arguments is stored on stack as Smi. We need to check
344  // that it really an Smi.
345  Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
346  GetExpression(0);
347  if (!number_of_args->IsSmi()) {
348  return false;
349  }
350  }
351  frame->ComputeCallerState(&state);
352  return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
353  iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
354 }
355 
356 
357 void SafeStackFrameIterator::Reset() {
358  if (is_working_iterator_) {
359  iterator_.Reset();
360  iteration_done_ = false;
361  }
362 }
363 
364 
365 // -------------------------------------------------------------------------
366 
367 
369  Isolate* isolate,
370  Address fp, Address sp, Address low_bound, Address high_bound) :
371  SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) {
372  if (!done() && !frame()->is_java_script()) Advance();
373 }
374 
375 
377  while (true) {
378  SafeJavaScriptFrameIterator::Advance();
379  if (done()) return;
380  if (frame()->is_java_script()) return;
381  }
382 }
383 
384 
385 Code* StackFrame::GetSafepointData(Isolate* isolate,
386  Address inner_pointer,
387  SafepointEntry* safepoint_entry,
388  unsigned* stack_slots) {
390  isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
391  if (!entry->safepoint_entry.is_valid()) {
392  entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
393  ASSERT(entry->safepoint_entry.is_valid());
394  } else {
395  ASSERT(entry->safepoint_entry.Equals(
396  entry->code->GetSafepointEntry(inner_pointer)));
397  }
398 
399  // Fill in the results and return the code.
400  Code* code = entry->code;
401  *safepoint_entry = entry->safepoint_entry;
402  *stack_slots = code->stack_slots();
403  return code;
404 }
405 
406 
407 bool StackFrame::HasHandler() const {
408  StackHandlerIterator it(this, top_handler());
409  return !it.done();
410 }
411 
412 
413 #ifdef DEBUG
414 static bool GcSafeCodeContains(HeapObject* object, Address addr);
415 #endif
416 
417 
418 void StackFrame::IteratePc(ObjectVisitor* v,
419  Address* pc_address,
420  Code* holder) {
421  Address pc = *pc_address;
422  ASSERT(GcSafeCodeContains(holder, pc));
423  unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
424  Object* code = holder;
425  v->VisitPointer(&code);
426  if (code != holder) {
427  holder = reinterpret_cast<Code*>(code);
428  pc = holder->instruction_start() + pc_offset;
429  *pc_address = pc;
430  }
431 }
432 
433 
434 void StackFrame::SetReturnAddressLocationResolver(
436  ASSERT(return_address_location_resolver == NULL);
437  return_address_location_resolver = resolver;
438 }
439 
440 
441 StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
442  ASSERT(state->fp != NULL);
444  return ARGUMENTS_ADAPTOR;
445  }
446  // The marker and function offsets overlap. If the marker isn't a
447  // smi then the frame is a JavaScript frame -- and the marker is
448  // really the function.
449  const int offset = StandardFrameConstants::kMarkerOffset;
450  Object* marker = Memory::Object_at(state->fp + offset);
451  if (!marker->IsSmi()) {
452  // If we're using a "safe" stack iterator, we treat optimized
453  // frames as normal JavaScript frames to avoid having to look
454  // into the heap to determine the state. This is safe as long
455  // as nobody tries to GC...
456  if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT;
457  Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind();
458  ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
459  return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
460  }
461  return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
462 }
463 
464 
465 
466 StackFrame::Type StackFrame::GetCallerState(State* state) const {
467  ComputeCallerState(state);
468  return ComputeType(isolate(), state);
469 }
470 
471 
472 Address StackFrame::UnpaddedFP() const {
473 #if defined(V8_TARGET_ARCH_IA32)
474  if (!is_optimized()) return fp();
475  int32_t alignment_state = Memory::int32_at(
477 
478  return (alignment_state == kAlignmentPaddingPushed) ?
479  (fp() + kPointerSize) : fp();
480 #else
481  return fp();
482 #endif
483 }
484 
485 
487  return HEAP->raw_unchecked_js_entry_code();
488 }
489 
490 
491 void EntryFrame::ComputeCallerState(State* state) const {
492  GetCallerState(state);
493 }
494 
495 
497  const int offset = EntryFrameConstants::kCallerFPOffset;
498  Memory::Address_at(this->fp() + offset) = caller_fp;
499 }
500 
501 
502 StackFrame::Type EntryFrame::GetCallerState(State* state) const {
503  const int offset = EntryFrameConstants::kCallerFPOffset;
504  Address fp = Memory::Address_at(this->fp() + offset);
505  return ExitFrame::GetStateForFramePointer(fp, state);
506 }
507 
508 
510  return HEAP->raw_unchecked_js_construct_entry_code();
511 }
512 
513 
515  const int offset = ExitFrameConstants::kCodeOffset;
516  return Memory::Object_at(fp() + offset);
517 }
518 
519 
521  return reinterpret_cast<Code*>(code_slot());
522 }
523 
524 
525 void ExitFrame::ComputeCallerState(State* state) const {
526  // Set up the caller state.
527  state->sp = caller_sp();
529  state->pc_address = ResolveReturnAddressLocation(
530  reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
531 }
532 
533 
536 }
537 
538 
539 void ExitFrame::Iterate(ObjectVisitor* v) const {
540  // The arguments are traversed as part of the expression stack of
541  // the calling frame.
542  IteratePc(v, pc_address(), LookupCode());
543  v->VisitPointer(&code_slot());
544 }
545 
546 
549 }
550 
551 
552 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
553  if (fp == 0) return NONE;
554  Address sp = ComputeStackPointer(fp);
555  FillState(fp, sp, state);
556  ASSERT(*state->pc_address != NULL);
557  return EXIT;
558 }
559 
560 
561 void ExitFrame::FillState(Address fp, Address sp, State* state) {
562  state->sp = sp;
563  state->fp = fp;
564  state->pc_address = ResolveReturnAddressLocation(
565  reinterpret_cast<Address*>(sp - 1 * kPointerSize));
566 }
567 
568 
571  return fp() + offset - n * kPointerSize;
572 }
573 
574 
576  return Memory::Object_at(GetExpressionAddress(fp, index));
577 }
578 
579 
582  return fp + offset - n * kPointerSize;
583 }
584 
585 
587  const int offset =
589  Address base = fp() + offset;
590  Address limit = sp();
591  ASSERT(base >= limit); // stack grows downwards
592  // Include register-allocated locals in number of expressions.
593  return static_cast<int>((base - limit) / kPointerSize);
594 }
595 
596 
597 void StandardFrame::ComputeCallerState(State* state) const {
598  state->sp = caller_sp();
599  state->fp = caller_fp();
600  state->pc_address = ResolveReturnAddressLocation(
601  reinterpret_cast<Address*>(ComputePCAddress(fp())));
602 }
603 
604 
607  caller_fp;
608 }
609 
610 
612  Address address = GetExpressionAddress(n);
613  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
614  if (it.handler()->includes(address)) return true;
615  }
616  return false;
617 }
618 
619 
620 void OptimizedFrame::Iterate(ObjectVisitor* v) const {
621 #ifdef DEBUG
622  // Make sure that optimized frames do not contain any stack handlers.
623  StackHandlerIterator it(this, top_handler());
624  ASSERT(it.done());
625 #endif
626 
627  // Make sure that we're not doing "safe" stack frame iteration. We cannot
628  // possibly find pointers in optimized frames in that state.
629  ASSERT(!SafeStackFrameIterator::is_active(isolate()));
630 
631  // Compute the safepoint information.
632  unsigned stack_slots = 0;
633  SafepointEntry safepoint_entry;
634  Code* code = StackFrame::GetSafepointData(
635  isolate(), pc(), &safepoint_entry, &stack_slots);
636  unsigned slot_space = stack_slots * kPointerSize;
637 
638  // Visit the outgoing parameters.
639  Object** parameters_base = &Memory::Object_at(sp());
640  Object** parameters_limit = &Memory::Object_at(
642 
643  // Visit the parameters that may be on top of the saved registers.
644  if (safepoint_entry.argument_count() > 0) {
645  v->VisitPointers(parameters_base,
646  parameters_base + safepoint_entry.argument_count());
647  parameters_base += safepoint_entry.argument_count();
648  }
649 
650  // Skip saved double registers.
651  if (safepoint_entry.has_doubles()) {
652  parameters_base += DoubleRegister::kNumAllocatableRegisters *
654  }
655 
656  // Visit the registers that contain pointers if any.
657  if (safepoint_entry.HasRegisters()) {
658  for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
659  if (safepoint_entry.HasRegisterAt(i)) {
660  int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
661  v->VisitPointer(parameters_base + reg_stack_index);
662  }
663  }
664  // Skip the words containing the register values.
665  parameters_base += kNumSafepointRegisters;
666  }
667 
668  // We're done dealing with the register bits.
669  uint8_t* safepoint_bits = safepoint_entry.bits();
670  safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
671 
672  // Visit the rest of the parameters.
673  v->VisitPointers(parameters_base, parameters_limit);
674 
675  // Visit pointer spill slots and locals.
676  for (unsigned index = 0; index < stack_slots; index++) {
677  int byte_index = index >> kBitsPerByteLog2;
678  int bit_index = index & (kBitsPerByte - 1);
679  if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
680  v->VisitPointer(parameters_limit + index);
681  }
682  }
683 
684  // Visit the context and the function.
685  Object** fixed_base = &Memory::Object_at(
687  Object** fixed_limit = &Memory::Object_at(fp());
688  v->VisitPointers(fixed_base, fixed_limit);
689 
690  // Visit the return address in the callee and incoming arguments.
691  IteratePc(v, pc_address(), code);
692 }
693 
694 
696  Address fp = caller_fp();
697  if (has_adapted_arguments()) {
698  // Skip the arguments adaptor frame and look at the real caller.
700  }
701  return IsConstructFrame(fp);
702 }
703 
704 
706  // If there is an arguments adaptor frame get the arguments length from it.
707  if (has_adapted_arguments()) {
708  return Smi::cast(GetExpression(caller_fp(), 0))->value();
709  } else {
711  }
712 }
713 
714 
716  JSFunction* function = JSFunction::cast(this->function());
717  return function->unchecked_code();
718 }
719 
720 
722  ASSERT(!SafeStackFrameIterator::is_active(isolate()) &&
723  isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
724 
725  JSFunction* function = JSFunction::cast(this->function());
726  return function->shared()->formal_parameter_count();
727 }
728 
729 
732 }
733 
734 
736  ASSERT(functions->length() == 0);
737  functions->Add(JSFunction::cast(function()));
738 }
739 
740 
742  ASSERT(functions->length() == 0);
743  Code* code_pointer = LookupCode();
744  int offset = static_cast<int>(pc() - code_pointer->address());
745  FrameSummary summary(receiver(),
746  JSFunction::cast(function()),
747  code_pointer,
748  offset,
749  IsConstructor());
750  functions->Add(summary);
751 }
752 
753 
755  bool print_args,
756  bool print_line_number) {
757  // constructor calls
758  HandleScope scope;
759  AssertNoAllocation no_allocation;
761  while (!it.done()) {
762  if (it.frame()->is_java_script()) {
763  JavaScriptFrame* frame = it.frame();
764  if (frame->IsConstructor()) PrintF(file, "new ");
765  // function name
766  Object* maybe_fun = frame->function();
767  if (maybe_fun->IsJSFunction()) {
768  JSFunction* fun = JSFunction::cast(maybe_fun);
769  fun->PrintName();
770  Code* js_code = frame->unchecked_code();
771  Address pc = frame->pc();
772  int code_offset =
773  static_cast<int>(pc - js_code->instruction_start());
774  PrintF("+%d", code_offset);
775  SharedFunctionInfo* shared = fun->shared();
776  if (print_line_number) {
777  Code* code = Code::cast(
778  v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
779  int source_pos = code->SourcePosition(pc);
780  Object* maybe_script = shared->script();
781  if (maybe_script->IsScript()) {
782  Handle<Script> script(Script::cast(maybe_script));
783  int line = GetScriptLineNumberSafe(script, source_pos) + 1;
784  Object* script_name_raw = script->name();
785  if (script_name_raw->IsString()) {
786  String* script_name = String::cast(script->name());
787  SmartArrayPointer<char> c_script_name =
788  script_name->ToCString(DISALLOW_NULLS,
790  PrintF(file, " at %s:%d", *c_script_name, line);
791  } else {
792  PrintF(file, " at <unknown>:%d", line);
793  }
794  } else {
795  PrintF(file, " at <unknown>:<unknown>");
796  }
797  }
798  } else {
799  PrintF("<unknown>");
800  }
801 
802  if (print_args) {
803  // function arguments
804  // (we are intentionally only printing the actually
805  // supplied parameters, not all parameters required)
806  PrintF(file, "(this=");
807  frame->receiver()->ShortPrint(file);
808  const int length = frame->ComputeParametersCount();
809  for (int i = 0; i < length; i++) {
810  PrintF(file, ", ");
811  frame->GetParameter(i)->ShortPrint(file);
812  }
813  PrintF(file, ")");
814  }
815  break;
816  }
817  it.Advance();
818  }
819 }
820 
821 
822 void FrameSummary::Print() {
823  PrintF("receiver: ");
824  receiver_->ShortPrint();
825  PrintF("\nfunction: ");
826  function_->shared()->DebugName()->ShortPrint();
827  PrintF("\ncode: ");
828  code_->ShortPrint();
829  if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
830  if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
831  PrintF("\npc: %d\n", offset_);
832 }
833 
834 
835 JSFunction* OptimizedFrame::LiteralAt(FixedArray* literal_array,
836  int literal_id) {
837  if (literal_id == Translation::kSelfLiteralId) {
838  return JSFunction::cast(function());
839  }
840 
841  return JSFunction::cast(literal_array->get(literal_id));
842 }
843 
844 
846  ASSERT(frames->length() == 0);
847  ASSERT(is_optimized());
848 
849  int deopt_index = Safepoint::kNoDeoptimizationIndex;
850  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
851  FixedArray* literal_array = data->LiteralArray();
852 
853  // BUG(3243555): Since we don't have a lazy-deopt registered at
854  // throw-statements, we can't use the translation at the call-site of
855  // throw. An entry with no deoptimization index indicates a call-site
856  // without a lazy-deopt. As a consequence we are not allowed to inline
857  // functions containing throw.
858  if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
860  return;
861  }
862 
863  TranslationIterator it(data->TranslationByteArray(),
864  data->TranslationIndex(deopt_index)->value());
865  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
866  ASSERT(opcode == Translation::BEGIN);
867  it.Next(); // Drop frame count.
868  int jsframe_count = it.Next();
869 
870  // We create the summary in reverse order because the frames
871  // in the deoptimization translation are ordered bottom-to-top.
872  bool is_constructor = IsConstructor();
873  int i = jsframe_count;
874  while (i > 0) {
875  opcode = static_cast<Translation::Opcode>(it.Next());
876  if (opcode == Translation::JS_FRAME) {
877  i--;
878  BailoutId ast_id = BailoutId(it.Next());
879  JSFunction* function = LiteralAt(literal_array, it.Next());
880  it.Next(); // Skip height.
881 
882  // The translation commands are ordered and the receiver is always
883  // at the first position. Since we are always at a call when we need
884  // to construct a stack trace, the receiver is always in a stack slot.
885  opcode = static_cast<Translation::Opcode>(it.Next());
886  ASSERT(opcode == Translation::STACK_SLOT ||
887  opcode == Translation::LITERAL);
888  int index = it.Next();
889 
890  // Get the correct receiver in the optimized frame.
891  Object* receiver = NULL;
892  if (opcode == Translation::LITERAL) {
893  receiver = data->LiteralArray()->get(index);
894  } else {
895  // Positive index means the value is spilled to the locals
896  // area. Negative means it is stored in the incoming parameter
897  // area.
898  if (index >= 0) {
899  receiver = GetExpression(index);
900  } else {
901  // Index -1 overlaps with last parameter, -n with the first parameter,
902  // (-n - 1) with the receiver with n being the number of parameters
903  // of the outermost, optimized frame.
904  int parameter_count = ComputeParametersCount();
905  int parameter_index = index + parameter_count;
906  receiver = (parameter_index == -1)
907  ? this->receiver()
908  : this->GetParameter(parameter_index);
909  }
910  }
911 
912  Code* code = function->shared()->code();
913  DeoptimizationOutputData* output_data =
914  DeoptimizationOutputData::cast(code->deoptimization_data());
915  unsigned entry = Deoptimizer::GetOutputInfo(output_data,
916  ast_id,
917  function->shared());
918  unsigned pc_offset =
920  ASSERT(pc_offset > 0);
921 
922  FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
923  frames->Add(summary);
924  is_constructor = false;
925  } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) {
926  // The next encountered JS_FRAME will be marked as a constructor call.
927  it.Skip(Translation::NumberOfOperandsFor(opcode));
928  ASSERT(!is_constructor);
929  is_constructor = true;
930  } else {
931  // Skip over operands to advance to the next opcode.
932  it.Skip(Translation::NumberOfOperandsFor(opcode));
933  }
934  }
935  ASSERT(!is_constructor);
936 }
937 
938 
940  int* deopt_index) {
941  ASSERT(is_optimized());
942 
943  JSFunction* opt_function = JSFunction::cast(function());
944  Code* code = opt_function->code();
945 
946  // The code object may have been replaced by lazy deoptimization. Fall
947  // back to a slow search in this case to find the original optimized
948  // code object.
949  if (!code->contains(pc())) {
950  code = isolate()->inner_pointer_to_code_cache()->
951  GcSafeFindCodeForInnerPointer(pc());
952  }
953  ASSERT(code != NULL);
954  ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
955 
956  SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
957  *deopt_index = safepoint_entry.deoptimization_index();
958  ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex);
959 
960  return DeoptimizationInputData::cast(code->deoptimization_data());
961 }
962 
963 
965  ASSERT(is_optimized());
966 
967  int deopt_index = Safepoint::kNoDeoptimizationIndex;
968  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
969 
970  TranslationIterator it(data->TranslationByteArray(),
971  data->TranslationIndex(deopt_index)->value());
972  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
973  ASSERT(opcode == Translation::BEGIN);
974  USE(opcode);
975  it.Next(); // Drop frame count.
976  int jsframe_count = it.Next();
977  return jsframe_count;
978 }
979 
980 
982  ASSERT(functions->length() == 0);
983  ASSERT(is_optimized());
984 
985  int deopt_index = Safepoint::kNoDeoptimizationIndex;
986  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
987  FixedArray* literal_array = data->LiteralArray();
988 
989  TranslationIterator it(data->TranslationByteArray(),
990  data->TranslationIndex(deopt_index)->value());
991  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
992  ASSERT(opcode == Translation::BEGIN);
993  it.Next(); // Drop frame count.
994  int jsframe_count = it.Next();
995 
996  // We insert the frames in reverse order because the frames
997  // in the deoptimization translation are ordered bottom-to-top.
998  while (jsframe_count > 0) {
999  opcode = static_cast<Translation::Opcode>(it.Next());
1000  if (opcode == Translation::JS_FRAME) {
1001  jsframe_count--;
1002  it.Next(); // Skip ast id.
1003  JSFunction* function = LiteralAt(literal_array, it.Next());
1004  it.Next(); // Skip height.
1005  functions->Add(function);
1006  } else {
1007  // Skip over operands to advance to the next opcode.
1008  it.Skip(Translation::NumberOfOperandsFor(opcode));
1009  }
1010  }
1011 }
1012 
1013 
1015  return Smi::cast(GetExpression(0))->value();
1016 }
1017 
1018 
1021 }
1022 
1023 
1025  // Internal frames have no arguments. The stack pointer of the
1026  // caller is at a fixed offset from the frame pointer.
1028 }
1029 
1030 
1032  return isolate()->builtins()->builtin(
1033  Builtins::kArgumentsAdaptorTrampoline);
1034 }
1035 
1036 
1038  const int offset = InternalFrameConstants::kCodeOffset;
1039  Object* code = Memory::Object_at(fp() + offset);
1040  ASSERT(code != NULL);
1041  return reinterpret_cast<Code*>(code);
1042 }
1043 
1044 
1045 void StackFrame::PrintIndex(StringStream* accumulator,
1046  PrintMode mode,
1047  int index) {
1048  accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1049 }
1050 
1051 
1053  PrintMode mode,
1054  int index) const {
1055  HandleScope scope;
1056  Object* receiver = this->receiver();
1057  Object* function = this->function();
1058 
1059  accumulator->PrintSecurityTokenIfChanged(function);
1060  PrintIndex(accumulator, mode, index);
1061  Code* code = NULL;
1062  if (IsConstructor()) accumulator->Add("new ");
1063  accumulator->PrintFunction(function, receiver, &code);
1064 
1065  // Get scope information for nicer output, if possible. If code is NULL, or
1066  // doesn't contain scope info, scope_info will return 0 for the number of
1067  // parameters, stack local variables, context local variables, stack slots,
1068  // or context slots.
1069  Handle<ScopeInfo> scope_info(ScopeInfo::Empty());
1070 
1071  if (function->IsJSFunction()) {
1072  Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
1073  scope_info = Handle<ScopeInfo>(shared->scope_info());
1074  Object* script_obj = shared->script();
1075  if (script_obj->IsScript()) {
1076  Handle<Script> script(Script::cast(script_obj));
1077  accumulator->Add(" [");
1078  accumulator->PrintName(script->name());
1079 
1080  Address pc = this->pc();
1081  if (code != NULL && code->kind() == Code::FUNCTION &&
1082  pc >= code->instruction_start() && pc < code->instruction_end()) {
1083  int source_pos = code->SourcePosition(pc);
1084  int line = GetScriptLineNumberSafe(script, source_pos) + 1;
1085  accumulator->Add(":%d", line);
1086  } else {
1087  int function_start_pos = shared->start_position();
1088  int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
1089  accumulator->Add(":~%d", line);
1090  }
1091 
1092  accumulator->Add("] ");
1093  }
1094  }
1095 
1096  accumulator->Add("(this=%o", receiver);
1097 
1098  // Print the parameters.
1099  int parameters_count = ComputeParametersCount();
1100  for (int i = 0; i < parameters_count; i++) {
1101  accumulator->Add(",");
1102  // If we have a name for the parameter we print it. Nameless
1103  // parameters are either because we have more actual parameters
1104  // than formal parameters or because we have no scope information.
1105  if (i < scope_info->ParameterCount()) {
1106  accumulator->PrintName(scope_info->ParameterName(i));
1107  accumulator->Add("=");
1108  }
1109  accumulator->Add("%o", GetParameter(i));
1110  }
1111 
1112  accumulator->Add(")");
1113  if (mode == OVERVIEW) {
1114  accumulator->Add("\n");
1115  return;
1116  }
1117  if (is_optimized()) {
1118  accumulator->Add(" {\n// optimized frame\n}\n");
1119  return;
1120  }
1121  accumulator->Add(" {\n");
1122 
1123  // Compute the number of locals and expression stack elements.
1124  int stack_locals_count = scope_info->StackLocalCount();
1125  int heap_locals_count = scope_info->ContextLocalCount();
1126  int expressions_count = ComputeExpressionsCount();
1127 
1128  // Print stack-allocated local variables.
1129  if (stack_locals_count > 0) {
1130  accumulator->Add(" // stack-allocated locals\n");
1131  }
1132  for (int i = 0; i < stack_locals_count; i++) {
1133  accumulator->Add(" var ");
1134  accumulator->PrintName(scope_info->StackLocalName(i));
1135  accumulator->Add(" = ");
1136  if (i < expressions_count) {
1137  accumulator->Add("%o", GetExpression(i));
1138  } else {
1139  accumulator->Add("// no expression found - inconsistent frame?");
1140  }
1141  accumulator->Add("\n");
1142  }
1143 
1144  // Try to get hold of the context of this frame.
1145  Context* context = NULL;
1146  if (this->context() != NULL && this->context()->IsContext()) {
1147  context = Context::cast(this->context());
1148  }
1149 
1150  // Print heap-allocated local variables.
1151  if (heap_locals_count > 0) {
1152  accumulator->Add(" // heap-allocated locals\n");
1153  }
1154  for (int i = 0; i < heap_locals_count; i++) {
1155  accumulator->Add(" var ");
1156  accumulator->PrintName(scope_info->ContextLocalName(i));
1157  accumulator->Add(" = ");
1158  if (context != NULL) {
1159  if (i < context->length()) {
1160  accumulator->Add("%o", context->get(Context::MIN_CONTEXT_SLOTS + i));
1161  } else {
1162  accumulator->Add(
1163  "// warning: missing context slot - inconsistent frame?");
1164  }
1165  } else {
1166  accumulator->Add("// warning: no context found - inconsistent frame?");
1167  }
1168  accumulator->Add("\n");
1169  }
1170 
1171  // Print the expression stack.
1172  int expressions_start = stack_locals_count;
1173  if (expressions_start < expressions_count) {
1174  accumulator->Add(" // expression stack (top to bottom)\n");
1175  }
1176  for (int i = expressions_count - 1; i >= expressions_start; i--) {
1177  if (IsExpressionInsideHandler(i)) continue;
1178  accumulator->Add(" [%02d] : %o\n", i, GetExpression(i));
1179  }
1180 
1181  // Print details about the function.
1182  if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1183  SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
1184  accumulator->Add("--------- s o u r c e c o d e ---------\n");
1185  shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
1186  accumulator->Add("\n-----------------------------------------\n");
1187  }
1188 
1189  accumulator->Add("}\n\n");
1190 }
1191 
1192 
1194  PrintMode mode,
1195  int index) const {
1196  int actual = ComputeParametersCount();
1197  int expected = -1;
1198  Object* function = this->function();
1199  if (function->IsJSFunction()) {
1200  expected = JSFunction::cast(function)->shared()->formal_parameter_count();
1201  }
1202 
1203  PrintIndex(accumulator, mode, index);
1204  accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1205  if (mode == OVERVIEW) {
1206  accumulator->Add("\n");
1207  return;
1208  }
1209  accumulator->Add(" {\n");
1210 
1211  // Print actual arguments.
1212  if (actual > 0) accumulator->Add(" // actual arguments\n");
1213  for (int i = 0; i < actual; i++) {
1214  accumulator->Add(" [%02d] : %o", i, GetParameter(i));
1215  if (expected != -1 && i >= expected) {
1216  accumulator->Add(" // not passed to callee");
1217  }
1218  accumulator->Add("\n");
1219  }
1220 
1221  accumulator->Add("}\n\n");
1222 }
1223 
1224 
1225 void EntryFrame::Iterate(ObjectVisitor* v) const {
1226  StackHandlerIterator it(this, top_handler());
1227  ASSERT(!it.done());
1228  StackHandler* handler = it.handler();
1229  ASSERT(handler->is_js_entry());
1230  handler->Iterate(v, LookupCode());
1231 #ifdef DEBUG
1232  // Make sure that the entry frame does not contain more than one
1233  // stack handler.
1234  it.Advance();
1235  ASSERT(it.done());
1236 #endif
1237  IteratePc(v, pc_address(), LookupCode());
1238 }
1239 
1240 
1241 void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
1242  const int offset = StandardFrameConstants::kContextOffset;
1243  Object** base = &Memory::Object_at(sp());
1244  Object** limit = &Memory::Object_at(fp() + offset) + 1;
1245  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1246  StackHandler* handler = it.handler();
1247  // Traverse pointers down to - but not including - the next
1248  // handler in the handler chain. Update the base to skip the
1249  // handler and allow the handler to traverse its own pointers.
1250  const Address address = handler->address();
1251  v->VisitPointers(base, reinterpret_cast<Object**>(address));
1252  base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1253  // Traverse the pointers in the handler itself.
1254  handler->Iterate(v, LookupCode());
1255  }
1256  v->VisitPointers(base, limit);
1257 }
1258 
1259 
1260 void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1261  IterateExpressions(v);
1262  IteratePc(v, pc_address(), LookupCode());
1263 }
1264 
1265 
1266 void InternalFrame::Iterate(ObjectVisitor* v) const {
1267  // Internal frames only have object pointers on the expression stack
1268  // as they never have any arguments.
1269  IterateExpressions(v);
1270  IteratePc(v, pc_address(), LookupCode());
1271 }
1272 
1273 
1274 // -------------------------------------------------------------------------
1275 
1276 
1277 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
1278  ASSERT(n >= 0);
1279  for (int i = 0; i <= n; i++) {
1280  while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1281  if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1282  iterator_.Advance();
1283  }
1284  UNREACHABLE();
1285  return NULL;
1286 }
1287 
1288 
1289 // -------------------------------------------------------------------------
1290 
1291 
1292 static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1293  MapWord map_word = object->map_word();
1294  return map_word.IsForwardingAddress() ?
1295  map_word.ToForwardingAddress()->map() : map_word.ToMap();
1296 }
1297 
1298 
1299 static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1300  return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1301 }
1302 
1303 
1304 #ifdef DEBUG
1305 static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1306  Map* map = GcSafeMapOfCodeSpaceObject(code);
1307  ASSERT(map == code->GetHeap()->code_map());
1308  Address start = code->address();
1309  Address end = code->address() + code->SizeFromMap(map);
1310  return start <= addr && addr < end;
1311 }
1312 #endif
1313 
1314 
1316  Address inner_pointer) {
1317  Code* code = reinterpret_cast<Code*>(object);
1318  ASSERT(code != NULL && GcSafeCodeContains(code, inner_pointer));
1319  return code;
1320 }
1321 
1322 
1324  Address inner_pointer) {
1325  Heap* heap = isolate_->heap();
1326  // Check if the inner pointer points into a large object chunk.
1327  LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1328  if (large_page != NULL) {
1329  return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1330  }
1331 
1332  // Iterate through the page until we reach the end or find an object starting
1333  // after the inner pointer.
1334  Page* page = Page::FromAddress(inner_pointer);
1335 
1336  Address addr = page->skip_list()->StartFor(inner_pointer);
1337 
1338  Address top = heap->code_space()->top();
1339  Address limit = heap->code_space()->limit();
1340 
1341  while (true) {
1342  if (addr == top && addr != limit) {
1343  addr = limit;
1344  continue;
1345  }
1346 
1347  HeapObject* obj = HeapObject::FromAddress(addr);
1348  int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1349  Address next_addr = addr + obj_size;
1350  if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1351  addr = next_addr;
1352  }
1353 }
1354 
1355 
1358  isolate_->counters()->pc_to_code()->Increment();
1359  ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize));
1360  uint32_t hash = ComputeIntegerHash(
1361  static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)),
1362  v8::internal::kZeroHashSeed);
1363  uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1364  InnerPointerToCodeCacheEntry* entry = cache(index);
1365  if (entry->inner_pointer == inner_pointer) {
1366  isolate_->counters()->pc_to_code_cached()->Increment();
1367  ASSERT(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
1368  } else {
1369  // Because this code may be interrupted by a profiling signal that
1370  // also queries the cache, we cannot update inner_pointer before the code
1371  // has been set. Otherwise, we risk trying to use a cache entry before
1372  // the code has been computed.
1373  entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
1374  entry->safepoint_entry.Reset();
1375  entry->inner_pointer = inner_pointer;
1376  }
1377  return entry;
1378 }
1379 
1380 
1381 // -------------------------------------------------------------------------
1382 
1383 int NumRegs(RegList reglist) {
1384  return CompilerIntrinsics::CountSetBits(reglist);
1385 }
1386 
1387 
1390 };
1391 
1393 
1395  int i = 0;
1396  for (int r = 0; r < kNumRegs; r++)
1397  if ((kJSCallerSaved & (1 << r)) != 0)
1398  caller_saved_code_data.reg_code[i++] = r;
1399 
1400  ASSERT(i == kNumJSCallerSaved);
1401 }
1402 
1403 int JSCallerSavedCode(int n) {
1404  ASSERT(0 <= n && n < kNumJSCallerSaved);
1405  return caller_saved_code_data.reg_code[n];
1406 }
1407 
1408 
1409 #define DEFINE_WRAPPER(type, field) \
1410 class field##_Wrapper : public ZoneObject { \
1411  public: /* NOLINT */ \
1412  field##_Wrapper(const field& original) : frame_(original) { \
1413  } \
1414  field frame_; \
1415 };
1417 #undef DEFINE_WRAPPER
1418 
1419 static StackFrame* AllocateFrameCopy(StackFrame* frame, Zone* zone) {
1420 #define FRAME_TYPE_CASE(type, field) \
1421  case StackFrame::type: { \
1422  field##_Wrapper* wrapper = \
1423  new(zone) field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
1424  return &wrapper->frame_; \
1425  }
1426 
1427  switch (frame->type()) {
1429  default: UNREACHABLE();
1430  }
1431 #undef FRAME_TYPE_CASE
1432  return NULL;
1433 }
1434 
1436  ZoneList<StackFrame*> list(10, zone);
1437  for (StackFrameIterator it; !it.done(); it.Advance()) {
1438  StackFrame* frame = AllocateFrameCopy(it.frame(), zone);
1439  list.Add(frame, zone);
1440  }
1441  return list.ToVector();
1442 }
1443 
1444 
1445 } } // namespace v8::internal
byte * Address
Definition: globals.h:157
virtual int GetNumberOfIncomingArguments() const
Definition: frames.cc:1014
Object * context() const
Definition: frames-inl.h:163
Definition: frames.h:56
static DeoptimizationOutputData * cast(Object *obj)
Object * function() const
Definition: frames-inl.h:231
static Object *& Object_at(Address addr)
Definition: v8memory.h:75
static void FillState(Address fp, Address sp, State *state)
Definition: frames.cc:561
virtual Address GetCallerStackPointer() const
Definition: frames.cc:1024
int GetArgumentsLength() const
Definition: frames.cc:705
void PrintF(const char *format,...)
Definition: v8utils.cc:40
Code * GcSafeCastToCode(HeapObject *object, Address inner_pointer)
Definition: frames.cc:1315
static String * cast(Object *obj)
#define FRAME_TYPE_CASE(type, field)
void SourceCodePrint(StringStream *accumulator, int max_length)
Definition: objects.cc:7963
static Type GetStateForFramePointer(Address fp, State *state)
Definition: frames.cc:552
virtual int GetInlineCount()
Definition: frames.cc:964
virtual Code * unchecked_code() const
Definition: frames.cc:1037
int NumRegs(RegList reglist)
Definition: frames.cc:1383
static MemoryChunk * FromAddress(Address a)
Definition: spaces.h:303
static bool IsArgumentsAdaptorFrame(Address fp)
Definition: frames-inl.h:184
Address GetExpressionAddress(int n) const
Definition: frames.cc:569
void PrintSecurityTokenIfChanged(Object *function)
Address caller_fp() const
Definition: frames-inl.h:169
int int32_t
Definition: unicode.cc:47
uint32_t RegList
Definition: frames.h:38
static const int kNumAllocatableRegisters
virtual void Summarize(List< FrameSummary > *frames)
Definition: frames.cc:741
Object * GetExpression(int index) const
Definition: frames-inl.h:153
virtual void SetCallerFp(Address caller_fp)
Definition: frames.cc:496
const int kBitsPerByteLog2
Definition: globals.h:238
byte * instruction_end()
Definition: objects-inl.h:4654
static Address handler(ThreadLocalTop *thread)
Definition: isolate.h:627
Object *& code_slot() const
Definition: frames.cc:514
int reg_code[kNumJSCallerSaved]
Definition: frames.cc:1389
#define ASSERT(condition)
Definition: checks.h:270
v8::Handle< v8::Value > Print(const v8::Arguments &args)
const RegList kJSCallerSaved
Definition: frames-arm.h:47
int ComputeExpressionsCount() const
Definition: frames.cc:586
static Script * cast(Object *obj)
int SourcePosition(Address pc)
Definition: objects.cc:8336
virtual Code * unchecked_code() const
Definition: frames.cc:486
void IterateExpressions(ObjectVisitor *v) const
Definition: frames.cc:1241
static Context * cast(Object *context)
Definition: contexts.h:212
Vector< StackFrame * > CreateStackMap(Zone *zone)
Definition: frames.cc:1435
virtual void ComputeCallerState(State *state) const
Definition: frames.cc:597
int ComputeParametersCount() const
Definition: frames.h:499
static Code * cast(Object *obj)
const int kAlignmentPaddingPushed
Definition: frames-ia32.h:57
virtual void GetFunctions(List< JSFunction * > *functions)
Definition: frames.cc:981
static Smi * cast(Object *object)
#define STACK_FRAME_TYPE_LIST(V)
Definition: frames.h:133
bool contains(byte *pc)
Definition: objects-inl.h:4690
void Add(Vector< const char > format, Vector< FmtElm > elms)
int JSCallerSavedCode(int n)
Definition: frames.cc:1403
SmartArrayPointer< char > ToCString(AllowNullsFlag allow_nulls, RobustnessFlag robustness_flag, int offset, int length, int *length_output=0)
Definition: objects.cc:6233
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:620
Object * receiver() const
Definition: frames-inl.h:216
virtual Code * unchecked_code() const
Definition: frames.cc:520
const Register sp
HANDLE HANDLE LPSTACKFRAME64 StackFrame
static const int kCallerPCOffset
Definition: frames-arm.h:129
#define UNREACHABLE()
Definition: checks.h:50
virtual Address GetCallerStackPointer() const
Definition: frames.cc:1019
static void PrintTop(FILE *file, bool print_args, bool print_line_number)
Definition: frames.cc:754
DeoptimizationInputData * GetDeoptimizationData(int *deopt_index)
Definition: frames.cc:939
bool IsConstructor() const
Definition: frames.cc:695
LargePage * FindPage(Address a)
Definition: spaces.cc:2711
static Address c_entry_fp(ThreadLocalTop *thread)
Definition: isolate.h:624
const int kDoubleSize
Definition: globals.h:218
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:1266
StackHandler * handler() const
Definition: frames.cc:71
static Address ComputePCAddress(Address fp)
Definition: frames-inl.h:179
static const int kCallerFPOffset
Definition: frames-arm.h:127
byte * instruction_start()
Definition: objects-inl.h:4649
const int kPointerSize
Definition: globals.h:220
static Address & Address_at(Address addr)
Definition: v8memory.h:71
uintptr_t(* ReturnAddressLocationResolver)(uintptr_t return_addr_location)
Definition: v8.h:2950
static int32_t & int32_at(Address addr)
Definition: v8memory.h:51
static unsigned decode(uint32_t value)
Definition: utils.h:273
static const int kDynamicAlignmentStateOffset
Definition: frames-ia32.h:127
virtual void Print(StringStream *accumulator, PrintMode mode, int index) const
Definition: frames.cc:1052
const Register pc
const int kNumJSCallerSaved
Definition: frames-arm.h:53
SafepointEntry GetSafepointEntry(Address pc)
Definition: objects.cc:8388
int GetScriptLineNumberSafe(Handle< Script > script, int code_pos)
Definition: handles.cc:517
virtual void Summarize(List< FrameSummary > *frames)
Definition: frames.cc:845
Code * code
Definition: frames.h:58
JavaScriptFrameIteratorTemp< SafeStackFrameIterator > SafeJavaScriptFrameIterator
Definition: frames.h:873
virtual Code * unchecked_code() const
Definition: frames.cc:715
OldSpace * code_space()
Definition: heap.h:508
static int GetOutputInfo(DeoptimizationOutputData *data, BailoutId node_id, SharedFunctionInfo *shared)
Definition: deoptimizer.cc:498
const int kBitsPerByte
Definition: globals.h:237
bool IsPowerOf2(T x)
Definition: utils.h:50
static JavaScriptFrame * cast(StackFrame *frame)
Definition: frames.h:532
LargeObjectSpace * lo_space()
Definition: heap.h:511
#define BASE_EMBEDDED
Definition: allocation.h:68
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:1225
static ScopeInfo * Empty()
Definition: scopeinfo.cc:152
HeapObject * GetObject()
Definition: spaces.h:754
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:1260
SafeStackTraceFrameIterator(Isolate *isolate, Address fp, Address sp, Address low_bound, Address high_bound)
Definition: frames.cc:368
virtual void SetCallerFp(Address caller_fp)
Definition: frames.cc:605
static const int kCallerSPDisplacement
Definition: frames-arm.h:133
virtual Code * unchecked_code() const
Definition: frames.cc:1031
virtual int GetNumberOfIncomingArguments() const
Definition: frames.cc:721
InnerPointerToCodeCache * inner_pointer_to_code_cache()
Definition: isolate.h:874
static Address ComputeStackPointer(Address fp)
void SetUpJSCallerSavedCodeData()
Definition: frames.cc:1394
uint32_t ComputeIntegerHash(uint32_t key, uint32_t seed)
Definition: utils.h:286
JavaScriptFrameIteratorTemp< StackFrameIterator > JavaScriptFrameIterator
Definition: frames.h:775
static const int kCallerFPOffset
Definition: frames-arm.h:117
InnerPointerToCodeCacheEntry * GetCacheEntry(Address inner_pointer)
Definition: frames.cc:1357
virtual void GetFunctions(List< JSFunction * > *functions)
Definition: frames.cc:735
const int kNumSafepointRegisters
Definition: frames-arm.h:92
virtual void Iterate(ObjectVisitor *v) const
Definition: frames.cc:539
static const int kHeaderSize
Definition: objects.h:4549
virtual Address GetCallerStackPointer() const
Definition: frames.cc:547
#define HEAP
Definition: isolate.h:1433
void PrintFunction(Object *function, Object *receiver, Code **code)
bool IsExpressionInsideHandler(int n) const
Definition: frames.cc:611
static HeapObject * FromAddress(Address address)
Definition: objects-inl.h:1171
void USE(T)
Definition: globals.h:289
Counters * counters()
Definition: isolate.h:819
virtual void Print(StringStream *accumulator, PrintMode mode, int index) const
Definition: frames.cc:1193
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
static bool IsConstructFrame(Address fp)
Definition: frames-inl.h:191
JSCallerSavedCodeData caller_saved_code_data
Definition: frames.cc:1392
void Add(const T &element, AllocationPolicy allocator=AllocationPolicy())
Definition: list-inl.h:38
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
Object * get(int index)
Definition: objects-inl.h:1737
SafepointEntry safepoint_entry
Definition: frames.h:59
SkipList * skip_list()
Definition: spaces.h:587
StackHandlerIterator(const StackFrame *frame, StackHandler *handler)
Definition: frames.cc:65
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
const Register fp
#define DEFINE_WRAPPER(type, field)
Definition: frames.cc:1409
#define INITIALIZE_SINGLETON(type, field)
Definition: frames.cc:90
Code * GcSafeFindCodeForInnerPointer(Address inner_pointer)
Definition: frames.cc:1323
virtual void SetCallerFp(Address caller_fp)
Definition: frames.cc:534
const int kNumRegs
Definition: frames-arm.h:43
Object * GetParameter(int index) const
Definition: frames-inl.h:211
bool has_adapted_arguments() const
Definition: frames-inl.h:226
Address StartFor(Address addr)
Definition: spaces.h:908
virtual Address GetCallerStackPointer() const
Definition: frames.cc:730
virtual Code * unchecked_code() const
Definition: frames.cc:509
static DeoptimizationInputData * cast(Object *obj)
static JSFunction * cast(Object *obj)