• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
ResolveReturnAddressLocation(Address * pc_address)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:
StackHandlerIterator(const StackFrame * frame,StackHandler * handler)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 
handler() const71   StackHandler* handler() const { return handler_; }
72 
done()73   bool done() {
74     return handler_ == NULL || handler_->address() > limit_;
75   }
Advance()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),
StackFrameIterator()91 StackFrameIterator::StackFrameIterator()
92     : isolate_(Isolate::Current()),
93       STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
94       frame_(NULL), handler_(NULL),
95       thread_(isolate_->thread_local_top()),
96       fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
97   Reset();
98 }
StackFrameIterator(Isolate * isolate)99 StackFrameIterator::StackFrameIterator(Isolate* isolate)
100     : isolate_(isolate),
101       STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
102       frame_(NULL), handler_(NULL),
103       thread_(isolate_->thread_local_top()),
104       fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
105   Reset();
106 }
StackFrameIterator(Isolate * isolate,ThreadLocalTop * t)107 StackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
108     : isolate_(isolate),
109       STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
110       frame_(NULL), handler_(NULL), thread_(t),
111       fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
112   Reset();
113 }
StackFrameIterator(Isolate * isolate,bool use_top,Address fp,Address sp)114 StackFrameIterator::StackFrameIterator(Isolate* isolate,
115                                        bool use_top, Address fp, Address sp)
116     : isolate_(isolate),
117       STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
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 
AdvanceWithHandler()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 
AdvanceWithoutHandler()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 
Reset()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 
SingletonFor(StackFrame::Type type,StackFrame::State * state)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 
SingletonFor(StackFrame::Type type)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;
201     STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
202     default: break;
203   }
204   return result;
205 
206 #undef FRAME_TYPE_CASE
207 }
208 
209 
210 // -------------------------------------------------------------------------
211 
212 
StackTraceFrameIterator()213 StackTraceFrameIterator::StackTraceFrameIterator() {
214   if (!done() && !IsValidFrame()) Advance();
215 }
216 
217 
StackTraceFrameIterator(Isolate * isolate)218 StackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
219     : JavaScriptFrameIterator(isolate) {
220   if (!done() && !IsValidFrame()) Advance();
221 }
222 
223 
Advance()224 void StackTraceFrameIterator::Advance() {
225   while (true) {
226     JavaScriptFrameIterator::Advance();
227     if (done()) return;
228     if (IsValidFrame()) return;
229   }
230 }
231 
IsValidFrame()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 
IsValidFP(Address fp)244 bool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
245   if (!validator_.IsValid(fp)) return false;
246   Address sp = ExitFrame::ComputeStackPointer(fp);
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 
ActiveCountMaintainer(Isolate * isolate)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 
~ActiveCountMaintainer()265 SafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() {
266   isolate_->set_safe_stack_iterator_counter(
267       isolate_->safe_stack_iterator_counter() - 1);
268 }
269 
270 
SafeStackFrameIterator(Isolate * isolate,Address fp,Address sp,Address low_bound,Address high_bound)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 
is_active(Isolate * isolate)283 bool SafeStackFrameIterator::is_active(Isolate* isolate) {
284   return isolate->safe_stack_iterator_counter() > 0;
285 }
286 
287 
IsValidTop(Isolate * isolate,Address low_bound,Address high_bound)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 
Advance()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 
CanIterateHandles(StackFrame * frame,StackHandler * handler)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 
IsValidFrame(StackFrame * frame) const326 bool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
327   return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
328 }
329 
330 
IsValidCaller(StackFrame * frame)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(
338         frame->fp() + EntryFrameConstants::kCallerFPOffset);
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 
Reset()357 void SafeStackFrameIterator::Reset() {
358   if (is_working_iterator_) {
359     iterator_.Reset();
360     iteration_done_ = false;
361   }
362 }
363 
364 
365 // -------------------------------------------------------------------------
366 
367 
SafeStackTraceFrameIterator(Isolate * isolate,Address fp,Address sp,Address low_bound,Address high_bound)368 SafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
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 
Advance()376 void SafeStackTraceFrameIterator::Advance() {
377   while (true) {
378     SafeJavaScriptFrameIterator::Advance();
379     if (done()) return;
380     if (frame()->is_java_script()) return;
381   }
382 }
383 
384 
GetSafepointData(Isolate * isolate,Address inner_pointer,SafepointEntry * safepoint_entry,unsigned * stack_slots)385 Code* StackFrame::GetSafepointData(Isolate* isolate,
386                                    Address inner_pointer,
387                                    SafepointEntry* safepoint_entry,
388                                    unsigned* stack_slots) {
389   InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
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 
HasHandler() const407 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 
IteratePc(ObjectVisitor * v,Address * pc_address,Code * holder)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 
SetReturnAddressLocationResolver(ReturnAddressLocationResolver resolver)434 void StackFrame::SetReturnAddressLocationResolver(
435     ReturnAddressLocationResolver resolver) {
436   ASSERT(return_address_location_resolver == NULL);
437   return_address_location_resolver = resolver;
438 }
439 
440 
ComputeType(Isolate * isolate,State * state)441 StackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
442   ASSERT(state->fp != NULL);
443   if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
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 
GetCallerState(State * state) const466 StackFrame::Type StackFrame::GetCallerState(State* state) const {
467   ComputeCallerState(state);
468   return ComputeType(isolate(), state);
469 }
470 
471 
unchecked_code() const472 Code* EntryFrame::unchecked_code() const {
473   return HEAP->raw_unchecked_js_entry_code();
474 }
475 
476 
ComputeCallerState(State * state) const477 void EntryFrame::ComputeCallerState(State* state) const {
478   GetCallerState(state);
479 }
480 
481 
SetCallerFp(Address caller_fp)482 void EntryFrame::SetCallerFp(Address caller_fp) {
483   const int offset = EntryFrameConstants::kCallerFPOffset;
484   Memory::Address_at(this->fp() + offset) = caller_fp;
485 }
486 
487 
GetCallerState(State * state) const488 StackFrame::Type EntryFrame::GetCallerState(State* state) const {
489   const int offset = EntryFrameConstants::kCallerFPOffset;
490   Address fp = Memory::Address_at(this->fp() + offset);
491   return ExitFrame::GetStateForFramePointer(fp, state);
492 }
493 
494 
unchecked_code() const495 Code* EntryConstructFrame::unchecked_code() const {
496   return HEAP->raw_unchecked_js_construct_entry_code();
497 }
498 
499 
code_slot() const500 Object*& ExitFrame::code_slot() const {
501   const int offset = ExitFrameConstants::kCodeOffset;
502   return Memory::Object_at(fp() + offset);
503 }
504 
505 
unchecked_code() const506 Code* ExitFrame::unchecked_code() const {
507   return reinterpret_cast<Code*>(code_slot());
508 }
509 
510 
ComputeCallerState(State * state) const511 void ExitFrame::ComputeCallerState(State* state) const {
512   // Set up the caller state.
513   state->sp = caller_sp();
514   state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
515   state->pc_address = ResolveReturnAddressLocation(
516       reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
517 }
518 
519 
SetCallerFp(Address caller_fp)520 void ExitFrame::SetCallerFp(Address caller_fp) {
521   Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
522 }
523 
524 
Iterate(ObjectVisitor * v) const525 void ExitFrame::Iterate(ObjectVisitor* v) const {
526   // The arguments are traversed as part of the expression stack of
527   // the calling frame.
528   IteratePc(v, pc_address(), LookupCode());
529   v->VisitPointer(&code_slot());
530 }
531 
532 
GetCallerStackPointer() const533 Address ExitFrame::GetCallerStackPointer() const {
534   return fp() + ExitFrameConstants::kCallerSPDisplacement;
535 }
536 
537 
GetStateForFramePointer(Address fp,State * state)538 StackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
539   if (fp == 0) return NONE;
540   Address sp = ComputeStackPointer(fp);
541   FillState(fp, sp, state);
542   ASSERT(*state->pc_address != NULL);
543   return EXIT;
544 }
545 
546 
FillState(Address fp,Address sp,State * state)547 void ExitFrame::FillState(Address fp, Address sp, State* state) {
548   state->sp = sp;
549   state->fp = fp;
550   state->pc_address = ResolveReturnAddressLocation(
551       reinterpret_cast<Address*>(sp - 1 * kPointerSize));
552 }
553 
554 
GetExpressionAddress(int n) const555 Address StandardFrame::GetExpressionAddress(int n) const {
556   const int offset = StandardFrameConstants::kExpressionsOffset;
557   return fp() + offset - n * kPointerSize;
558 }
559 
560 
GetExpression(Address fp,int index)561 Object* StandardFrame::GetExpression(Address fp, int index) {
562   return Memory::Object_at(GetExpressionAddress(fp, index));
563 }
564 
565 
GetExpressionAddress(Address fp,int n)566 Address StandardFrame::GetExpressionAddress(Address fp, int n) {
567   const int offset = StandardFrameConstants::kExpressionsOffset;
568   return fp + offset - n * kPointerSize;
569 }
570 
571 
ComputeExpressionsCount() const572 int StandardFrame::ComputeExpressionsCount() const {
573   const int offset =
574       StandardFrameConstants::kExpressionsOffset + kPointerSize;
575   Address base = fp() + offset;
576   Address limit = sp();
577   ASSERT(base >= limit);  // stack grows downwards
578   // Include register-allocated locals in number of expressions.
579   return static_cast<int>((base - limit) / kPointerSize);
580 }
581 
582 
ComputeCallerState(State * state) const583 void StandardFrame::ComputeCallerState(State* state) const {
584   state->sp = caller_sp();
585   state->fp = caller_fp();
586   state->pc_address = ResolveReturnAddressLocation(
587       reinterpret_cast<Address*>(ComputePCAddress(fp())));
588 }
589 
590 
SetCallerFp(Address caller_fp)591 void StandardFrame::SetCallerFp(Address caller_fp) {
592   Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
593       caller_fp;
594 }
595 
596 
IsExpressionInsideHandler(int n) const597 bool StandardFrame::IsExpressionInsideHandler(int n) const {
598   Address address = GetExpressionAddress(n);
599   for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
600     if (it.handler()->includes(address)) return true;
601   }
602   return false;
603 }
604 
605 
Iterate(ObjectVisitor * v) const606 void OptimizedFrame::Iterate(ObjectVisitor* v) const {
607 #ifdef DEBUG
608   // Make sure that optimized frames do not contain any stack handlers.
609   StackHandlerIterator it(this, top_handler());
610   ASSERT(it.done());
611 #endif
612 
613   // Make sure that we're not doing "safe" stack frame iteration. We cannot
614   // possibly find pointers in optimized frames in that state.
615   ASSERT(!SafeStackFrameIterator::is_active(isolate()));
616 
617   // Compute the safepoint information.
618   unsigned stack_slots = 0;
619   SafepointEntry safepoint_entry;
620   Code* code = StackFrame::GetSafepointData(
621       isolate(), pc(), &safepoint_entry, &stack_slots);
622   unsigned slot_space = stack_slots * kPointerSize;
623 
624   // Visit the outgoing parameters.
625   Object** parameters_base = &Memory::Object_at(sp());
626   Object** parameters_limit = &Memory::Object_at(
627       fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
628 
629   // Visit the parameters that may be on top of the saved registers.
630   if (safepoint_entry.argument_count() > 0) {
631     v->VisitPointers(parameters_base,
632                      parameters_base + safepoint_entry.argument_count());
633     parameters_base += safepoint_entry.argument_count();
634   }
635 
636   // Skip saved double registers.
637   if (safepoint_entry.has_doubles()) {
638     parameters_base += DoubleRegister::kNumAllocatableRegisters *
639         kDoubleSize / kPointerSize;
640   }
641 
642   // Visit the registers that contain pointers if any.
643   if (safepoint_entry.HasRegisters()) {
644     for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
645       if (safepoint_entry.HasRegisterAt(i)) {
646         int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
647         v->VisitPointer(parameters_base + reg_stack_index);
648       }
649     }
650     // Skip the words containing the register values.
651     parameters_base += kNumSafepointRegisters;
652   }
653 
654   // We're done dealing with the register bits.
655   uint8_t* safepoint_bits = safepoint_entry.bits();
656   safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
657 
658   // Visit the rest of the parameters.
659   v->VisitPointers(parameters_base, parameters_limit);
660 
661   // Visit pointer spill slots and locals.
662   for (unsigned index = 0; index < stack_slots; index++) {
663     int byte_index = index >> kBitsPerByteLog2;
664     int bit_index = index & (kBitsPerByte - 1);
665     if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
666       v->VisitPointer(parameters_limit + index);
667     }
668   }
669 
670   // Visit the context and the function.
671   Object** fixed_base = &Memory::Object_at(
672       fp() + JavaScriptFrameConstants::kFunctionOffset);
673   Object** fixed_limit = &Memory::Object_at(fp());
674   v->VisitPointers(fixed_base, fixed_limit);
675 
676   // Visit the return address in the callee and incoming arguments.
677   IteratePc(v, pc_address(), code);
678 }
679 
680 
IsConstructor() const681 bool JavaScriptFrame::IsConstructor() const {
682   Address fp = caller_fp();
683   if (has_adapted_arguments()) {
684     // Skip the arguments adaptor frame and look at the real caller.
685     fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
686   }
687   return IsConstructFrame(fp);
688 }
689 
690 
GetArgumentsLength() const691 int JavaScriptFrame::GetArgumentsLength() const {
692   // If there is an arguments adaptor frame get the arguments length from it.
693   if (has_adapted_arguments()) {
694     return Smi::cast(GetExpression(caller_fp(), 0))->value();
695   } else {
696     return GetNumberOfIncomingArguments();
697   }
698 }
699 
700 
unchecked_code() const701 Code* JavaScriptFrame::unchecked_code() const {
702   JSFunction* function = JSFunction::cast(this->function());
703   return function->unchecked_code();
704 }
705 
706 
GetNumberOfIncomingArguments() const707 int JavaScriptFrame::GetNumberOfIncomingArguments() const {
708   ASSERT(!SafeStackFrameIterator::is_active(isolate()) &&
709          isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
710 
711   JSFunction* function = JSFunction::cast(this->function());
712   return function->shared()->formal_parameter_count();
713 }
714 
715 
GetCallerStackPointer() const716 Address JavaScriptFrame::GetCallerStackPointer() const {
717   return fp() + StandardFrameConstants::kCallerSPOffset;
718 }
719 
720 
GetFunctions(List<JSFunction * > * functions)721 void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
722   ASSERT(functions->length() == 0);
723   functions->Add(JSFunction::cast(function()));
724 }
725 
726 
Summarize(List<FrameSummary> * functions)727 void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
728   ASSERT(functions->length() == 0);
729   Code* code_pointer = LookupCode();
730   int offset = static_cast<int>(pc() - code_pointer->address());
731   FrameSummary summary(receiver(),
732                        JSFunction::cast(function()),
733                        code_pointer,
734                        offset,
735                        IsConstructor());
736   functions->Add(summary);
737 }
738 
739 
PrintTop(FILE * file,bool print_args,bool print_line_number)740 void JavaScriptFrame::PrintTop(FILE* file,
741                                bool print_args,
742                                bool print_line_number) {
743   // constructor calls
744   HandleScope scope;
745   AssertNoAllocation no_allocation;
746   JavaScriptFrameIterator it;
747   while (!it.done()) {
748     if (it.frame()->is_java_script()) {
749       JavaScriptFrame* frame = it.frame();
750       if (frame->IsConstructor()) PrintF(file, "new ");
751       // function name
752       Object* maybe_fun = frame->function();
753       if (maybe_fun->IsJSFunction()) {
754         JSFunction* fun = JSFunction::cast(maybe_fun);
755         fun->PrintName();
756         Code* js_code = frame->unchecked_code();
757         Address pc = frame->pc();
758         int code_offset =
759             static_cast<int>(pc - js_code->instruction_start());
760         PrintF("+%d", code_offset);
761         SharedFunctionInfo* shared = fun->shared();
762         if (print_line_number) {
763           Code* code = Code::cast(
764               v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
765           int source_pos = code->SourcePosition(pc);
766           Object* maybe_script = shared->script();
767           if (maybe_script->IsScript()) {
768             Handle<Script> script(Script::cast(maybe_script));
769             int line = GetScriptLineNumberSafe(script, source_pos) + 1;
770             Object* script_name_raw = script->name();
771             if (script_name_raw->IsString()) {
772               String* script_name = String::cast(script->name());
773               SmartArrayPointer<char> c_script_name =
774                   script_name->ToCString(DISALLOW_NULLS,
775                                          ROBUST_STRING_TRAVERSAL);
776               PrintF(file, " at %s:%d", *c_script_name, line);
777             } else {
778               PrintF(file, "at <unknown>:%d", line);
779             }
780           } else {
781             PrintF(file, " at <unknown>:<unknown>");
782           }
783         }
784       } else {
785         PrintF("<unknown>");
786       }
787 
788       if (print_args) {
789         // function arguments
790         // (we are intentionally only printing the actually
791         // supplied parameters, not all parameters required)
792         PrintF(file, "(this=");
793         frame->receiver()->ShortPrint(file);
794         const int length = frame->ComputeParametersCount();
795         for (int i = 0; i < length; i++) {
796           PrintF(file, ", ");
797           frame->GetParameter(i)->ShortPrint(file);
798         }
799         PrintF(file, ")");
800       }
801       break;
802     }
803     it.Advance();
804   }
805 }
806 
807 
Print()808 void FrameSummary::Print() {
809   PrintF("receiver: ");
810   receiver_->ShortPrint();
811   PrintF("\nfunction: ");
812   function_->shared()->DebugName()->ShortPrint();
813   PrintF("\ncode: ");
814   code_->ShortPrint();
815   if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
816   if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
817   PrintF("\npc: %d\n", offset_);
818 }
819 
820 
Summarize(List<FrameSummary> * frames)821 void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
822   ASSERT(frames->length() == 0);
823   ASSERT(is_optimized());
824 
825   int deopt_index = Safepoint::kNoDeoptimizationIndex;
826   DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
827 
828   // BUG(3243555): Since we don't have a lazy-deopt registered at
829   // throw-statements, we can't use the translation at the call-site of
830   // throw. An entry with no deoptimization index indicates a call-site
831   // without a lazy-deopt. As a consequence we are not allowed to inline
832   // functions containing throw.
833   if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
834     JavaScriptFrame::Summarize(frames);
835     return;
836   }
837 
838   TranslationIterator it(data->TranslationByteArray(),
839                          data->TranslationIndex(deopt_index)->value());
840   Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
841   ASSERT(opcode == Translation::BEGIN);
842   it.Next();  // Drop frame count.
843   int jsframe_count = it.Next();
844 
845   // We create the summary in reverse order because the frames
846   // in the deoptimization translation are ordered bottom-to-top.
847   bool is_constructor = IsConstructor();
848   int i = jsframe_count;
849   while (i > 0) {
850     opcode = static_cast<Translation::Opcode>(it.Next());
851     if (opcode == Translation::JS_FRAME) {
852       i--;
853       int ast_id = it.Next();
854       int function_id = it.Next();
855       it.Next();  // Skip height.
856       JSFunction* function =
857           JSFunction::cast(data->LiteralArray()->get(function_id));
858 
859       // The translation commands are ordered and the receiver is always
860       // at the first position. Since we are always at a call when we need
861       // to construct a stack trace, the receiver is always in a stack slot.
862       opcode = static_cast<Translation::Opcode>(it.Next());
863       ASSERT(opcode == Translation::STACK_SLOT ||
864              opcode == Translation::LITERAL);
865       int index = it.Next();
866 
867       // Get the correct receiver in the optimized frame.
868       Object* receiver = NULL;
869       if (opcode == Translation::LITERAL) {
870         receiver = data->LiteralArray()->get(index);
871       } else {
872         // Positive index means the value is spilled to the locals
873         // area. Negative means it is stored in the incoming parameter
874         // area.
875         if (index >= 0) {
876           receiver = GetExpression(index);
877         } else {
878           // Index -1 overlaps with last parameter, -n with the first parameter,
879           // (-n - 1) with the receiver with n being the number of parameters
880           // of the outermost, optimized frame.
881           int parameter_count = ComputeParametersCount();
882           int parameter_index = index + parameter_count;
883           receiver = (parameter_index == -1)
884               ? this->receiver()
885               : this->GetParameter(parameter_index);
886         }
887       }
888 
889       Code* code = function->shared()->code();
890       DeoptimizationOutputData* output_data =
891           DeoptimizationOutputData::cast(code->deoptimization_data());
892       unsigned entry = Deoptimizer::GetOutputInfo(output_data,
893                                                   ast_id,
894                                                   function->shared());
895       unsigned pc_offset =
896           FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
897       ASSERT(pc_offset > 0);
898 
899       FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
900       frames->Add(summary);
901       is_constructor = false;
902     } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) {
903       // The next encountered JS_FRAME will be marked as a constructor call.
904       it.Skip(Translation::NumberOfOperandsFor(opcode));
905       ASSERT(!is_constructor);
906       is_constructor = true;
907     } else {
908       // Skip over operands to advance to the next opcode.
909       it.Skip(Translation::NumberOfOperandsFor(opcode));
910     }
911   }
912   ASSERT(!is_constructor);
913 }
914 
915 
GetDeoptimizationData(int * deopt_index)916 DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
917     int* deopt_index) {
918   ASSERT(is_optimized());
919 
920   JSFunction* opt_function = JSFunction::cast(function());
921   Code* code = opt_function->code();
922 
923   // The code object may have been replaced by lazy deoptimization. Fall
924   // back to a slow search in this case to find the original optimized
925   // code object.
926   if (!code->contains(pc())) {
927     code = isolate()->inner_pointer_to_code_cache()->
928         GcSafeFindCodeForInnerPointer(pc());
929   }
930   ASSERT(code != NULL);
931   ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
932 
933   SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
934   *deopt_index = safepoint_entry.deoptimization_index();
935   ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex);
936 
937   return DeoptimizationInputData::cast(code->deoptimization_data());
938 }
939 
940 
GetInlineCount()941 int OptimizedFrame::GetInlineCount() {
942   ASSERT(is_optimized());
943 
944   int deopt_index = Safepoint::kNoDeoptimizationIndex;
945   DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
946 
947   TranslationIterator it(data->TranslationByteArray(),
948                          data->TranslationIndex(deopt_index)->value());
949   Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
950   ASSERT(opcode == Translation::BEGIN);
951   USE(opcode);
952   it.Next();  // Drop frame count.
953   int jsframe_count = it.Next();
954   return jsframe_count;
955 }
956 
957 
GetFunctions(List<JSFunction * > * functions)958 void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
959   ASSERT(functions->length() == 0);
960   ASSERT(is_optimized());
961 
962   int deopt_index = Safepoint::kNoDeoptimizationIndex;
963   DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
964 
965   TranslationIterator it(data->TranslationByteArray(),
966                          data->TranslationIndex(deopt_index)->value());
967   Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
968   ASSERT(opcode == Translation::BEGIN);
969   it.Next();  // Drop frame count.
970   int jsframe_count = it.Next();
971 
972   // We insert the frames in reverse order because the frames
973   // in the deoptimization translation are ordered bottom-to-top.
974   while (jsframe_count > 0) {
975     opcode = static_cast<Translation::Opcode>(it.Next());
976     if (opcode == Translation::JS_FRAME) {
977       jsframe_count--;
978       it.Next();  // Skip ast id.
979       int function_id = it.Next();
980       it.Next();  // Skip height.
981       JSFunction* function =
982           JSFunction::cast(data->LiteralArray()->get(function_id));
983       functions->Add(function);
984     } else {
985       // Skip over operands to advance to the next opcode.
986       it.Skip(Translation::NumberOfOperandsFor(opcode));
987     }
988   }
989 }
990 
991 
GetNumberOfIncomingArguments() const992 int ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
993   return Smi::cast(GetExpression(0))->value();
994 }
995 
996 
GetCallerStackPointer() const997 Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
998   return fp() + StandardFrameConstants::kCallerSPOffset;
999 }
1000 
1001 
GetCallerStackPointer() const1002 Address InternalFrame::GetCallerStackPointer() const {
1003   // Internal frames have no arguments. The stack pointer of the
1004   // caller is at a fixed offset from the frame pointer.
1005   return fp() + StandardFrameConstants::kCallerSPOffset;
1006 }
1007 
1008 
unchecked_code() const1009 Code* ArgumentsAdaptorFrame::unchecked_code() const {
1010   return isolate()->builtins()->builtin(
1011       Builtins::kArgumentsAdaptorTrampoline);
1012 }
1013 
1014 
unchecked_code() const1015 Code* InternalFrame::unchecked_code() const {
1016   const int offset = InternalFrameConstants::kCodeOffset;
1017   Object* code = Memory::Object_at(fp() + offset);
1018   ASSERT(code != NULL);
1019   return reinterpret_cast<Code*>(code);
1020 }
1021 
1022 
PrintIndex(StringStream * accumulator,PrintMode mode,int index)1023 void StackFrame::PrintIndex(StringStream* accumulator,
1024                             PrintMode mode,
1025                             int index) {
1026   accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1027 }
1028 
1029 
Print(StringStream * accumulator,PrintMode mode,int index) const1030 void JavaScriptFrame::Print(StringStream* accumulator,
1031                             PrintMode mode,
1032                             int index) const {
1033   HandleScope scope;
1034   Object* receiver = this->receiver();
1035   Object* function = this->function();
1036 
1037   accumulator->PrintSecurityTokenIfChanged(function);
1038   PrintIndex(accumulator, mode, index);
1039   Code* code = NULL;
1040   if (IsConstructor()) accumulator->Add("new ");
1041   accumulator->PrintFunction(function, receiver, &code);
1042 
1043   // Get scope information for nicer output, if possible. If code is NULL, or
1044   // doesn't contain scope info, scope_info will return 0 for the number of
1045   // parameters, stack local variables, context local variables, stack slots,
1046   // or context slots.
1047   Handle<ScopeInfo> scope_info(ScopeInfo::Empty());
1048 
1049   if (function->IsJSFunction()) {
1050     Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
1051     scope_info = Handle<ScopeInfo>(shared->scope_info());
1052     Object* script_obj = shared->script();
1053     if (script_obj->IsScript()) {
1054       Handle<Script> script(Script::cast(script_obj));
1055       accumulator->Add(" [");
1056       accumulator->PrintName(script->name());
1057 
1058       Address pc = this->pc();
1059       if (code != NULL && code->kind() == Code::FUNCTION &&
1060           pc >= code->instruction_start() && pc < code->instruction_end()) {
1061         int source_pos = code->SourcePosition(pc);
1062         int line = GetScriptLineNumberSafe(script, source_pos) + 1;
1063         accumulator->Add(":%d", line);
1064       } else {
1065         int function_start_pos = shared->start_position();
1066         int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
1067         accumulator->Add(":~%d", line);
1068       }
1069 
1070       accumulator->Add("] ");
1071     }
1072   }
1073 
1074   accumulator->Add("(this=%o", receiver);
1075 
1076   // Print the parameters.
1077   int parameters_count = ComputeParametersCount();
1078   for (int i = 0; i < parameters_count; i++) {
1079     accumulator->Add(",");
1080     // If we have a name for the parameter we print it. Nameless
1081     // parameters are either because we have more actual parameters
1082     // than formal parameters or because we have no scope information.
1083     if (i < scope_info->ParameterCount()) {
1084       accumulator->PrintName(scope_info->ParameterName(i));
1085       accumulator->Add("=");
1086     }
1087     accumulator->Add("%o", GetParameter(i));
1088   }
1089 
1090   accumulator->Add(")");
1091   if (mode == OVERVIEW) {
1092     accumulator->Add("\n");
1093     return;
1094   }
1095   if (is_optimized()) {
1096     accumulator->Add(" {\n// optimized frame\n}\n");
1097     return;
1098   }
1099   accumulator->Add(" {\n");
1100 
1101   // Compute the number of locals and expression stack elements.
1102   int stack_locals_count = scope_info->StackLocalCount();
1103   int heap_locals_count = scope_info->ContextLocalCount();
1104   int expressions_count = ComputeExpressionsCount();
1105 
1106   // Print stack-allocated local variables.
1107   if (stack_locals_count > 0) {
1108     accumulator->Add("  // stack-allocated locals\n");
1109   }
1110   for (int i = 0; i < stack_locals_count; i++) {
1111     accumulator->Add("  var ");
1112     accumulator->PrintName(scope_info->StackLocalName(i));
1113     accumulator->Add(" = ");
1114     if (i < expressions_count) {
1115       accumulator->Add("%o", GetExpression(i));
1116     } else {
1117       accumulator->Add("// no expression found - inconsistent frame?");
1118     }
1119     accumulator->Add("\n");
1120   }
1121 
1122   // Try to get hold of the context of this frame.
1123   Context* context = NULL;
1124   if (this->context() != NULL && this->context()->IsContext()) {
1125     context = Context::cast(this->context());
1126   }
1127 
1128   // Print heap-allocated local variables.
1129   if (heap_locals_count > 0) {
1130     accumulator->Add("  // heap-allocated locals\n");
1131   }
1132   for (int i = 0; i < heap_locals_count; i++) {
1133     accumulator->Add("  var ");
1134     accumulator->PrintName(scope_info->ContextLocalName(i));
1135     accumulator->Add(" = ");
1136     if (context != NULL) {
1137       if (i < context->length()) {
1138         accumulator->Add("%o", context->get(Context::MIN_CONTEXT_SLOTS + i));
1139       } else {
1140         accumulator->Add(
1141             "// warning: missing context slot - inconsistent frame?");
1142       }
1143     } else {
1144       accumulator->Add("// warning: no context found - inconsistent frame?");
1145     }
1146     accumulator->Add("\n");
1147   }
1148 
1149   // Print the expression stack.
1150   int expressions_start = stack_locals_count;
1151   if (expressions_start < expressions_count) {
1152     accumulator->Add("  // expression stack (top to bottom)\n");
1153   }
1154   for (int i = expressions_count - 1; i >= expressions_start; i--) {
1155     if (IsExpressionInsideHandler(i)) continue;
1156     accumulator->Add("  [%02d] : %o\n", i, GetExpression(i));
1157   }
1158 
1159   // Print details about the function.
1160   if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1161     SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
1162     accumulator->Add("--------- s o u r c e   c o d e ---------\n");
1163     shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
1164     accumulator->Add("\n-----------------------------------------\n");
1165   }
1166 
1167   accumulator->Add("}\n\n");
1168 }
1169 
1170 
Print(StringStream * accumulator,PrintMode mode,int index) const1171 void ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1172                                   PrintMode mode,
1173                                   int index) const {
1174   int actual = ComputeParametersCount();
1175   int expected = -1;
1176   Object* function = this->function();
1177   if (function->IsJSFunction()) {
1178     expected = JSFunction::cast(function)->shared()->formal_parameter_count();
1179   }
1180 
1181   PrintIndex(accumulator, mode, index);
1182   accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1183   if (mode == OVERVIEW) {
1184     accumulator->Add("\n");
1185     return;
1186   }
1187   accumulator->Add(" {\n");
1188 
1189   // Print actual arguments.
1190   if (actual > 0) accumulator->Add("  // actual arguments\n");
1191   for (int i = 0; i < actual; i++) {
1192     accumulator->Add("  [%02d] : %o", i, GetParameter(i));
1193     if (expected != -1 && i >= expected) {
1194       accumulator->Add("  // not passed to callee");
1195     }
1196     accumulator->Add("\n");
1197   }
1198 
1199   accumulator->Add("}\n\n");
1200 }
1201 
1202 
Iterate(ObjectVisitor * v) const1203 void EntryFrame::Iterate(ObjectVisitor* v) const {
1204   StackHandlerIterator it(this, top_handler());
1205   ASSERT(!it.done());
1206   StackHandler* handler = it.handler();
1207   ASSERT(handler->is_js_entry());
1208   handler->Iterate(v, LookupCode());
1209 #ifdef DEBUG
1210   // Make sure that the entry frame does not contain more than one
1211   // stack handler.
1212   it.Advance();
1213   ASSERT(it.done());
1214 #endif
1215   IteratePc(v, pc_address(), LookupCode());
1216 }
1217 
1218 
IterateExpressions(ObjectVisitor * v) const1219 void StandardFrame::IterateExpressions(ObjectVisitor* v) const {
1220   const int offset = StandardFrameConstants::kContextOffset;
1221   Object** base = &Memory::Object_at(sp());
1222   Object** limit = &Memory::Object_at(fp() + offset) + 1;
1223   for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1224     StackHandler* handler = it.handler();
1225     // Traverse pointers down to - but not including - the next
1226     // handler in the handler chain. Update the base to skip the
1227     // handler and allow the handler to traverse its own pointers.
1228     const Address address = handler->address();
1229     v->VisitPointers(base, reinterpret_cast<Object**>(address));
1230     base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1231     // Traverse the pointers in the handler itself.
1232     handler->Iterate(v, LookupCode());
1233   }
1234   v->VisitPointers(base, limit);
1235 }
1236 
1237 
Iterate(ObjectVisitor * v) const1238 void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1239   IterateExpressions(v);
1240   IteratePc(v, pc_address(), LookupCode());
1241 }
1242 
1243 
Iterate(ObjectVisitor * v) const1244 void InternalFrame::Iterate(ObjectVisitor* v) const {
1245   // Internal frames only have object pointers on the expression stack
1246   // as they never have any arguments.
1247   IterateExpressions(v);
1248   IteratePc(v, pc_address(), LookupCode());
1249 }
1250 
1251 
1252 // -------------------------------------------------------------------------
1253 
1254 
FindJavaScriptFrame(int n)1255 JavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
1256   ASSERT(n >= 0);
1257   for (int i = 0; i <= n; i++) {
1258     while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1259     if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1260     iterator_.Advance();
1261   }
1262   UNREACHABLE();
1263   return NULL;
1264 }
1265 
1266 
1267 // -------------------------------------------------------------------------
1268 
1269 
GcSafeMapOfCodeSpaceObject(HeapObject * object)1270 static Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
1271   MapWord map_word = object->map_word();
1272   return map_word.IsForwardingAddress() ?
1273       map_word.ToForwardingAddress()->map() : map_word.ToMap();
1274 }
1275 
1276 
GcSafeSizeOfCodeSpaceObject(HeapObject * object)1277 static int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
1278   return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
1279 }
1280 
1281 
1282 #ifdef DEBUG
GcSafeCodeContains(HeapObject * code,Address addr)1283 static bool GcSafeCodeContains(HeapObject* code, Address addr) {
1284   Map* map = GcSafeMapOfCodeSpaceObject(code);
1285   ASSERT(map == code->GetHeap()->code_map());
1286   Address start = code->address();
1287   Address end = code->address() + code->SizeFromMap(map);
1288   return start <= addr && addr < end;
1289 }
1290 #endif
1291 
1292 
GcSafeCastToCode(HeapObject * object,Address inner_pointer)1293 Code* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
1294                                                 Address inner_pointer) {
1295   Code* code = reinterpret_cast<Code*>(object);
1296   ASSERT(code != NULL && GcSafeCodeContains(code, inner_pointer));
1297   return code;
1298 }
1299 
1300 
GcSafeFindCodeForInnerPointer(Address inner_pointer)1301 Code* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
1302     Address inner_pointer) {
1303   Heap* heap = isolate_->heap();
1304   // Check if the inner pointer points into a large object chunk.
1305   LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
1306   if (large_page != NULL) {
1307     return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
1308   }
1309 
1310   // Iterate through the page until we reach the end or find an object starting
1311   // after the inner pointer.
1312   Page* page = Page::FromAddress(inner_pointer);
1313 
1314   Address addr = page->skip_list()->StartFor(inner_pointer);
1315 
1316   Address top = heap->code_space()->top();
1317   Address limit = heap->code_space()->limit();
1318 
1319   while (true) {
1320     if (addr == top && addr != limit) {
1321       addr = limit;
1322       continue;
1323     }
1324 
1325     HeapObject* obj = HeapObject::FromAddress(addr);
1326     int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
1327     Address next_addr = addr + obj_size;
1328     if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
1329     addr = next_addr;
1330   }
1331 }
1332 
1333 
1334 InnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
GetCacheEntry(Address inner_pointer)1335     InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
1336   isolate_->counters()->pc_to_code()->Increment();
1337   ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize));
1338   uint32_t hash = ComputeIntegerHash(
1339       static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)),
1340       v8::internal::kZeroHashSeed);
1341   uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
1342   InnerPointerToCodeCacheEntry* entry = cache(index);
1343   if (entry->inner_pointer == inner_pointer) {
1344     isolate_->counters()->pc_to_code_cached()->Increment();
1345     ASSERT(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
1346   } else {
1347     // Because this code may be interrupted by a profiling signal that
1348     // also queries the cache, we cannot update inner_pointer before the code
1349     // has been set. Otherwise, we risk trying to use a cache entry before
1350     // the code has been computed.
1351     entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
1352     entry->safepoint_entry.Reset();
1353     entry->inner_pointer = inner_pointer;
1354   }
1355   return entry;
1356 }
1357 
1358 
1359 // -------------------------------------------------------------------------
1360 
NumRegs(RegList reglist)1361 int NumRegs(RegList reglist) {
1362   int n = 0;
1363   while (reglist != 0) {
1364     n++;
1365     reglist &= reglist - 1;  // clear one bit
1366   }
1367   return n;
1368 }
1369 
1370 
1371 struct JSCallerSavedCodeData {
JSCallerSavedCodeDatav8::internal::JSCallerSavedCodeData1372   JSCallerSavedCodeData() {
1373     int i = 0;
1374     for (int r = 0; r < kNumRegs; r++)
1375       if ((kJSCallerSaved & (1 << r)) != 0)
1376         reg_code[i++] = r;
1377 
1378     ASSERT(i == kNumJSCallerSaved);
1379   }
1380   int reg_code[kNumJSCallerSaved];
1381 };
1382 
1383 
1384 static LazyInstance<JSCallerSavedCodeData>::type caller_saved_code_data =
1385     LAZY_INSTANCE_INITIALIZER;
1386 
JSCallerSavedCode(int n)1387 int JSCallerSavedCode(int n) {
1388   ASSERT(0 <= n && n < kNumJSCallerSaved);
1389   return caller_saved_code_data.Get().reg_code[n];
1390 }
1391 
1392 
1393 #define DEFINE_WRAPPER(type, field)                              \
1394 class field##_Wrapper : public ZoneObject {                      \
1395  public:  /* NOLINT */                                           \
1396   field##_Wrapper(const field& original) : frame_(original) {    \
1397   }                                                              \
1398   field frame_;                                                  \
1399 };
STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)1400 STACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
1401 #undef DEFINE_WRAPPER
1402 
1403 static StackFrame* AllocateFrameCopy(StackFrame* frame) {
1404 #define FRAME_TYPE_CASE(type, field) \
1405   case StackFrame::type: { \
1406     field##_Wrapper* wrapper = \
1407         new field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
1408     return &wrapper->frame_; \
1409   }
1410 
1411   switch (frame->type()) {
1412     STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
1413     default: UNREACHABLE();
1414   }
1415 #undef FRAME_TYPE_CASE
1416   return NULL;
1417 }
1418 
CreateStackMap()1419 Vector<StackFrame*> CreateStackMap() {
1420   ZoneList<StackFrame*> list(10);
1421   for (StackFrameIterator it; !it.done(); it.Advance()) {
1422     StackFrame* frame = AllocateFrameCopy(it.frame());
1423     list.Add(frame);
1424   }
1425   return list.ToVector();
1426 }
1427 
1428 
1429 } }  // namespace v8::internal
1430