13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "ast.h"
31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "frames-inl.h"
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h"
343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#include "lazy-instance.h"
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "mark-compact.h"
36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "safepoint-table.h"
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "scopeinfo.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "string-stream.h"
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "allocation-inl.h"
413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic ReturnAddressLocationResolver return_address_location_resolver = NULL;
473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Resolves pc_address through the resolution address function if one is set.
503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic inline Address* ResolveReturnAddressLocation(Address* pc_address) {
513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (return_address_location_resolver == NULL) {
523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return pc_address;
533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  } else {
543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return reinterpret_cast<Address*>(
553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        return_address_location_resolver(
563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            reinterpret_cast<uintptr_t>(pc_address)));
573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Iterator that supports traversing the stack handlers of a
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// particular frame. Needs to know the top of the handler chain.
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass StackHandlerIterator BASE_EMBEDDED {
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackHandlerIterator(const StackFrame* frame, StackHandler* handler)
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      : limit_(frame->fp()), handler_(handler) {
67a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Make sure the handler has already been unwound to this frame.
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(frame->sp() <= handler->address());
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackHandler* handler() const { return handler_; }
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool done() {
74a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return handler_ == NULL || handler_->address() > limit_;
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  void Advance() {
77a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(!done());
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    handler_ = handler_->next();
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const Address limit_;
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackHandler* handler_;
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define INITIALIZE_SINGLETON(type, field) field##_(this),
91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStackFrameIterator::StackFrameIterator()
928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : isolate_(Isolate::Current()),
938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      frame_(NULL), handler_(NULL),
958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      thread_(isolate_->thread_local_top()),
968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Reset();
988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
998b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochStackFrameIterator::StackFrameIterator(Isolate* isolate)
1008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : isolate_(isolate),
1018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
10244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      frame_(NULL), handler_(NULL),
1038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      thread_(isolate_->thread_local_top()),
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Reset();
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1078b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochStackFrameIterator::StackFrameIterator(Isolate* isolate, ThreadLocalTop* t)
1088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : isolate_(isolate),
1098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      frame_(NULL), handler_(NULL), thread_(t),
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fp_(NULL), sp_(NULL), advance_(&StackFrameIterator::AdvanceWithHandler) {
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Reset();
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
11444f0eee88ff00398ff7f715fab053374d808c90dSteve BlockStackFrameIterator::StackFrameIterator(Isolate* isolate,
11544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                       bool use_top, Address fp, Address sp)
1168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : isolate_(isolate),
1178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      STACK_FRAME_TYPE_LIST(INITIALIZE_SINGLETON)
118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      frame_(NULL), handler_(NULL),
1198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      thread_(use_top ? isolate_->thread_local_top() : NULL),
120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      fp_(use_top ? NULL : fp), sp_(sp),
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      advance_(use_top ? &StackFrameIterator::AdvanceWithHandler :
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block               &StackFrameIterator::AdvanceWithoutHandler) {
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (use_top || fp != NULL) {
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Reset();
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef INITIALIZE_SINGLETON
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StackFrameIterator::AdvanceWithHandler() {
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!done());
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the state of the calling frame before restoring
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // callee-saved registers and unwinding handlers. This allows the
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // frame code that computes the caller state to access the top
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // handler and the value of any callee-saved register if needed.
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame::State state;
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame::Type type = frame_->GetCallerState(&state);
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Unwind handlers corresponding to the current frame.
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackHandlerIterator it(frame_, handler_);
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (!it.done()) it.Advance();
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  handler_ = it.handler();
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Advance to the calling frame.
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_ = SingletonFor(type, &state);
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // When we're done iterating over the stack frames, the handler
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // chain must have been completely unwound.
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!done() || handler_ == NULL);
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StackFrameIterator::AdvanceWithoutHandler() {
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // A simpler version of Advance which doesn't care about handler.
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!done());
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame::State state;
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame::Type type = frame_->GetCallerState(&state);
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_ = SingletonFor(type, &state);
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StackFrameIterator::Reset() {
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame::State state;
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame::Type type;
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (thread_ != NULL) {
16744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    type = ExitFrame::GetStateForFramePointer(
16844f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Isolate::c_entry_fp(thread_), &state);
16944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    handler_ = StackHandler::FromAddress(
17044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        Isolate::handler(thread_));
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(fp_ != NULL);
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    state.fp = fp_;
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    state.sp = sp_;
1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    state.pc_address = ResolveReturnAddressLocation(
1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        reinterpret_cast<Address*>(StandardFrame::ComputePCAddress(fp_)));
1778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    type = StackFrame::ComputeType(isolate(), &state);
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1790d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (SingletonFor(type) == NULL) return;
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame_ = SingletonFor(type, &state);
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type,
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                             StackFrame::State* state) {
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (type == StackFrame::NONE) return NULL;
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame* result = SingletonFor(type);
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(result != NULL);
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result->state_ = *state;
190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStackFrame* StackFrameIterator::SingletonFor(StackFrame::Type type) {
195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define FRAME_TYPE_CASE(type, field) \
196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  case StackFrame::type: result = &field##_; break;
197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame* result = NULL;
199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (type) {
200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case StackFrame::NONE: return NULL;
201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default: break;
203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result;
205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef FRAME_TYPE_CASE
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStackTraceFrameIterator::StackTraceFrameIterator() {
2144515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke  if (!done() && !IsValidFrame()) Advance();
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2188b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochStackTraceFrameIterator::StackTraceFrameIterator(Isolate* isolate)
2198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : JavaScriptFrameIterator(isolate) {
2208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  if (!done() && !IsValidFrame()) Advance();
2218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
2228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StackTraceFrameIterator::Advance() {
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    JavaScriptFrameIterator::Advance();
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (done()) return;
2284515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (IsValidFrame()) return;
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2324515c472dc3e5ed2448a564600976759e569a0a8Leon Clarkebool StackTraceFrameIterator::IsValidFrame() {
2334515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    if (!frame()->function()->IsJSFunction()) return false;
2344515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    Object* script = JSFunction::cast(frame()->function())->shared()->script();
2354515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    // Don't show functions from native scripts to user.
2364515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke    return (script->IsScript() &&
2374515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke            Script::TYPE_NATIVE != Script::cast(script)->type()->value());
2384515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke}
2394515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2440d5e116f6aee03185f237311a943491bb079a768Kristian Monsenbool SafeStackFrameIterator::ExitFrameValidator::IsValidFP(Address fp) {
2450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!validator_.IsValid(fp)) return false;
2460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Address sp = ExitFrame::ComputeStackPointer(fp);
2470d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!validator_.IsValid(sp)) return false;
2480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  StackFrame::State state;
2490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ExitFrame::FillState(fp, sp, &state);
2500d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!validator_.IsValid(reinterpret_cast<Address>(state.pc_address))) {
2510d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    return false;
2520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  }
2530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return *state.pc_address != NULL;
2540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
2550d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2560d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2578b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochSafeStackFrameIterator::ActiveCountMaintainer::ActiveCountMaintainer(
2588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Isolate* isolate)
2598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    : isolate_(isolate) {
2608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  isolate_->set_safe_stack_iterator_counter(
2618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      isolate_->safe_stack_iterator_counter() + 1);
2628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
2638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2658b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochSafeStackFrameIterator::ActiveCountMaintainer::~ActiveCountMaintainer() {
2668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  isolate_->set_safe_stack_iterator_counter(
2678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      isolate_->safe_stack_iterator_counter() - 1);
2688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
2698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
2708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSafeStackFrameIterator::SafeStackFrameIterator(
27244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Isolate* isolate,
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address fp, Address sp, Address low_bound, Address high_bound) :
2748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    maintainer_(isolate),
2750d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    stack_validator_(low_bound, high_bound),
27644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    is_valid_top_(IsValidTop(isolate, low_bound, high_bound)),
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    is_valid_fp_(IsWithinBounds(low_bound, high_bound, fp)),
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    is_working_iterator_(is_valid_top_ || is_valid_fp_),
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    iteration_done_(!is_working_iterator_),
28044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    iterator_(isolate, is_valid_top_, is_valid_fp_ ? fp : NULL, sp) {
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
2838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochbool SafeStackFrameIterator::is_active(Isolate* isolate) {
2848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return isolate->safe_stack_iterator_counter() > 0;
2858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
2868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockbool SafeStackFrameIterator::IsValidTop(Isolate* isolate,
28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                        Address low_bound, Address high_bound) {
29044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ThreadLocalTop* top = isolate->thread_local_top();
29144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Address fp = Isolate::c_entry_fp(top);
2920d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ExitFrameValidator validator(low_bound, high_bound);
2930d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (!validator.IsValidFP(fp)) return false;
29444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return Isolate::handler(top) != NULL;
2950d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
2960d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
2970d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid SafeStackFrameIterator::Advance() {
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(is_working_iterator_);
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!done());
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame* last_frame = iterator_.frame();
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address last_sp = last_frame->sp(), last_fp = last_frame->fp();
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Before advancing to the next stack frame, perform pointer validity tests
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  iteration_done_ = !IsValidFrame(last_frame) ||
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      !CanIterateHandles(last_frame, iterator_.handler()) ||
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      !IsValidCaller(last_frame);
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (iteration_done_) return;
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  iterator_.Advance();
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (iterator_.done()) return;
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that we have actually moved to the previous frame in the stack
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame* prev_frame = iterator_.frame();
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  iteration_done_ = prev_frame->sp() < last_sp || prev_frame->fp() < last_fp;
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool SafeStackFrameIterator::CanIterateHandles(StackFrame* frame,
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                               StackHandler* handler) {
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If StackIterator iterates over StackHandles, verify that
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // StackHandlerIterator can be instantiated (see StackHandlerIterator
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // constructor.)
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return !is_valid_top_ || (frame->sp() <= handler->address());
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool SafeStackFrameIterator::IsValidFrame(StackFrame* frame) const {
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return IsValidStackAddress(frame->sp()) && IsValidStackAddress(frame->fp());
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool SafeStackFrameIterator::IsValidCaller(StackFrame* frame) {
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackFrame::State state;
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (frame->is_entry() || frame->is_entry_construct()) {
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // See EntryFrame::GetCallerState. It computes the caller FP address
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and calls ExitFrame::GetStateForFramePointer on it. We need to be
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // sure that caller FP address is valid.
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address caller_fp = Memory::Address_at(
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        frame->fp() + EntryFrameConstants::kCallerFPOffset);
3390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    ExitFrameValidator validator(stack_validator_);
3400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen    if (!validator.IsValidFP(caller_fp)) return false;
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else if (frame->is_arguments_adaptor()) {
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // See ArgumentsAdaptorFrame::GetCallerStackPointer. It assumes that
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // the number of arguments is stored on stack as Smi. We need to check
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // that it really an Smi.
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Object* number_of_args = reinterpret_cast<ArgumentsAdaptorFrame*>(frame)->
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        GetExpression(0);
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (!number_of_args->IsSmi()) {
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return false;
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  frame->ComputeCallerState(&state);
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return IsValidStackAddress(state.sp) && IsValidStackAddress(state.fp) &&
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      iterator_.SingletonFor(frame->GetCallerState(&state)) != NULL;
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid SafeStackFrameIterator::Reset() {
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (is_working_iterator_) {
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    iterator_.Reset();
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    iteration_done_ = false;
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockSafeStackTraceFrameIterator::SafeStackTraceFrameIterator(
36944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Isolate* isolate,
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Address fp, Address sp, Address low_bound, Address high_bound) :
37144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    SafeJavaScriptFrameIterator(isolate, fp, sp, low_bound, high_bound) {
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (!done() && !frame()->is_java_script()) Advance();
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid SafeStackTraceFrameIterator::Advance() {
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (true) {
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SafeJavaScriptFrameIterator::Advance();
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (done()) return;
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (frame()->is_java_script()) return;
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3858b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochCode* StackFrame::GetSafepointData(Isolate* isolate,
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   Address inner_pointer,
387b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                                   SafepointEntry* safepoint_entry,
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   unsigned* stack_slots) {
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InnerPointerToCodeCache::InnerPointerToCodeCacheEntry* entry =
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate->inner_pointer_to_code_cache()->GetCacheEntry(inner_pointer);
391b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (!entry->safepoint_entry.is_valid()) {
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    entry->safepoint_entry = entry->code->GetSafepointEntry(inner_pointer);
393b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    ASSERT(entry->safepoint_entry.is_valid());
394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(entry->safepoint_entry.Equals(
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        entry->code->GetSafepointEntry(inner_pointer)));
397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Fill in the results and return the code.
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Code* code = entry->code;
401b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  *safepoint_entry = entry->safepoint_entry;
402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  *stack_slots = code->stack_slots();
403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return code;
404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool StackFrame::HasHandler() const {
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackHandlerIterator it(this, top_handler());
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return !it.done();
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool GcSafeCodeContains(HeapObject* object, Address addr);
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
41880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid StackFrame::IteratePc(ObjectVisitor* v,
41980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                           Address* pc_address,
42080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen                           Code* holder) {
42180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Address pc = *pc_address;
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(GcSafeCodeContains(holder, pc));
42380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
42480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Object* code = holder;
42580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  v->VisitPointer(&code);
42680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (code != holder) {
42780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    holder = reinterpret_cast<Code*>(code);
42880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    pc = holder->instruction_start() + pc_offset;
42980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    *pc_address = pc;
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StackFrame::SetReturnAddressLocationResolver(
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ReturnAddressLocationResolver resolver) {
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(return_address_location_resolver == NULL);
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return_address_location_resolver = resolver;
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4418b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochStackFrame::Type StackFrame::ComputeType(Isolate* isolate, State* state) {
44280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  ASSERT(state->fp != NULL);
44380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
44480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    return ARGUMENTS_ADAPTOR;
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
44680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The marker and function offsets overlap. If the marker isn't a
44780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // smi then the frame is a JavaScript frame -- and the marker is
44880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // really the function.
44980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  const int offset = StandardFrameConstants::kMarkerOffset;
45080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Object* marker = Memory::Object_at(state->fp + offset);
451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!marker->IsSmi()) {
452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // If we're using a "safe" stack iterator, we treat optimized
453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // frames as normal JavaScript frames to avoid having to look
454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // into the heap to determine the state. This is safe as long
455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // as nobody tries to GC...
4568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (SafeStackFrameIterator::is_active(isolate)) return JAVA_SCRIPT;
4578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Code::Kind kind = GetContainingCode(isolate, *(state->pc_address))->kind();
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
46180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStackFrame::Type StackFrame::GetCallerState(State* state) const {
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ComputeCallerState(state);
4688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return ComputeType(isolate(), state);
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
472756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickCode* EntryFrame::unchecked_code() const {
47344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return HEAP->raw_unchecked_js_entry_code();
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid EntryFrame::ComputeCallerState(State* state) const {
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  GetCallerState(state);
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
4826ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid EntryFrame::SetCallerFp(Address caller_fp) {
4836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  const int offset = EntryFrameConstants::kCallerFPOffset;
4846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Memory::Address_at(this->fp() + offset) = caller_fp;
4856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
4866ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
4876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockStackFrame::Type EntryFrame::GetCallerState(State* state) const {
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int offset = EntryFrameConstants::kCallerFPOffset;
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address fp = Memory::Address_at(this->fp() + offset);
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return ExitFrame::GetStateForFramePointer(fp, state);
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
495756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickCode* EntryConstructFrame::unchecked_code() const {
49644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  return HEAP->raw_unchecked_js_construct_entry_code();
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
500d0582a6c46733687d045e4188a1bcd0123c758a1Steve BlockObject*& ExitFrame::code_slot() const {
501d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  const int offset = ExitFrameConstants::kCodeOffset;
502d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return Memory::Object_at(fp() + offset);
503d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block}
504d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
505d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block
506756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickCode* ExitFrame::unchecked_code() const {
507756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  return reinterpret_cast<Code*>(code_slot());
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ExitFrame::ComputeCallerState(State* state) const {
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Set up the caller state.
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state->sp = caller_sp();
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state->fp = Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset);
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  state->pc_address = ResolveReturnAddressLocation(
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<Address*>(fp() + ExitFrameConstants::kCallerPCOffset));
517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid ExitFrame::SetCallerFp(Address caller_fp) {
5216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Memory::Address_at(fp() + ExitFrameConstants::kCallerFPOffset) = caller_fp;
5226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
52580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsenvoid ExitFrame::Iterate(ObjectVisitor* v) const {
52680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // The arguments are traversed as part of the expression stack of
52780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // the calling frame.
5288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  IteratePc(v, pc_address(), LookupCode());
52980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  v->VisitPointer(&code_slot());
53080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
53180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
53280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress ExitFrame::GetCallerStackPointer() const {
534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return fp() + ExitFrameConstants::kCallerSPDisplacement;
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5380d5e116f6aee03185f237311a943491bb079a768Kristian MonsenStackFrame::Type ExitFrame::GetStateForFramePointer(Address fp, State* state) {
5390d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  if (fp == 0) return NONE;
5400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  Address sp = ComputeStackPointer(fp);
5410d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  FillState(fp, sp, state);
5420d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  ASSERT(*state->pc_address != NULL);
5430d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  return EXIT;
5440d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5450d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5460d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5470d5e116f6aee03185f237311a943491bb079a768Kristian Monsenvoid ExitFrame::FillState(Address fp, Address sp, State* state) {
5480d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  state->sp = sp;
5490d5e116f6aee03185f237311a943491bb079a768Kristian Monsen  state->fp = fp;
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  state->pc_address = ResolveReturnAddressLocation(
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<Address*>(sp - 1 * kPointerSize));
5520d5e116f6aee03185f237311a943491bb079a768Kristian Monsen}
5530d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
5540d5e116f6aee03185f237311a943491bb079a768Kristian Monsen
555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockAddress StandardFrame::GetExpressionAddress(int n) const {
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int offset = StandardFrameConstants::kExpressionsOffset;
557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return fp() + offset - n * kPointerSize;
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5613fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochObject* StandardFrame::GetExpression(Address fp, int index) {
5623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return Memory::Object_at(GetExpressionAddress(fp, index));
5633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5663fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochAddress StandardFrame::GetExpressionAddress(Address fp, int n) {
5673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  const int offset = StandardFrameConstants::kExpressionsOffset;
5683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  return fp + offset - n * kPointerSize;
5693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
5703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
5713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint StandardFrame::ComputeExpressionsCount() const {
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int offset =
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      StandardFrameConstants::kExpressionsOffset + kPointerSize;
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address base = fp() + offset;
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address limit = sp();
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(base >= limit);  // stack grows downwards
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Include register-allocated locals in number of expressions.
579d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  return static_cast<int>((base - limit) / kPointerSize);
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StandardFrame::ComputeCallerState(State* state) const {
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state->sp = caller_sp();
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  state->fp = caller_fp();
5863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  state->pc_address = ResolveReturnAddressLocation(
5873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      reinterpret_cast<Address*>(ComputePCAddress(fp())));
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
5916ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockvoid StandardFrame::SetCallerFp(Address caller_fp) {
5926ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  Memory::Address_at(fp() + StandardFrameConstants::kCallerFPOffset) =
5936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      caller_fp;
5946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
5956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool StandardFrame::IsExpressionInsideHandler(int n) const {
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address address = GetExpressionAddress(n);
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (it.handler()->includes(address)) return true;
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid OptimizedFrame::Iterate(ObjectVisitor* v) const {
607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Make sure that optimized frames do not contain any stack handlers.
609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StackHandlerIterator it(this, top_handler());
610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(it.done());
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Make sure that we're not doing "safe" stack frame iteration. We cannot
614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // possibly find pointers in optimized frames in that state.
6158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!SafeStackFrameIterator::is_active(isolate()));
616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compute the safepoint information.
618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned stack_slots = 0;
619b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  SafepointEntry safepoint_entry;
620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Code* code = StackFrame::GetSafepointData(
6218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      isolate(), pc(), &safepoint_entry, &stack_slots);
622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned slot_space = stack_slots * kPointerSize;
623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
6248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // Visit the outgoing parameters.
625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Object** parameters_base = &Memory::Object_at(sp());
626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Object** parameters_limit = &Memory::Object_at(
627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
629b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Visit the parameters that may be on top of the saved registers.
630b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (safepoint_entry.argument_count() > 0) {
631b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    v->VisitPointers(parameters_base,
632b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch                     parameters_base + safepoint_entry.argument_count());
633b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    parameters_base += safepoint_entry.argument_count();
634b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
635b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
636b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  // Skip saved double registers.
637b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (safepoint_entry.has_doubles()) {
638b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    parameters_base += DoubleRegister::kNumAllocatableRegisters *
639b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch        kDoubleSize / kPointerSize;
640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  }
641b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Visit the registers that contain pointers if any.
643b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  if (safepoint_entry.HasRegisters()) {
644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
645b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch      if (safepoint_entry.HasRegisterAt(i)) {
646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        v->VisitPointer(parameters_base + reg_stack_index);
648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Skip the words containing the register values.
651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    parameters_base += kNumSafepointRegisters;
652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We're done dealing with the register bits.
655b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  uint8_t* safepoint_bits = safepoint_entry.bits();
656b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  safepoint_bits += kNumSafepointRegisters >> kBitsPerByteLog2;
657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Visit the rest of the parameters.
659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v->VisitPointers(parameters_base, parameters_limit);
660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Visit pointer spill slots and locals.
662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (unsigned index = 0; index < stack_slots; index++) {
663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int byte_index = index >> kBitsPerByteLog2;
664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int bit_index = index & (kBitsPerByte - 1);
665b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    if ((safepoint_bits[byte_index] & (1U << bit_index)) != 0) {
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      v->VisitPointer(parameters_limit + index);
667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Visit the context and the function.
671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Object** fixed_base = &Memory::Object_at(
672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      fp() + JavaScriptFrameConstants::kFunctionOffset);
673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Object** fixed_limit = &Memory::Object_at(fp());
674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  v->VisitPointers(fixed_base, fixed_limit);
675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Visit the return address in the callee and incoming arguments.
677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  IteratePc(v, pc_address(), code);
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockbool JavaScriptFrame::IsConstructor() const {
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address fp = caller_fp();
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (has_adapted_arguments()) {
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Skip the arguments adaptor frame and look at the real caller.
685a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    fp = Memory::Address_at(fp + StandardFrameConstants::kCallerFPOffset);
686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return IsConstructFrame(fp);
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint JavaScriptFrame::GetArgumentsLength() const {
6923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // If there is an arguments adaptor frame get the arguments length from it.
6933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (has_adapted_arguments()) {
6943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return Smi::cast(GetExpression(caller_fp(), 0))->value();
6953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  } else {
6963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    return GetNumberOfIncomingArguments();
6973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
6983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
6993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
701756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickCode* JavaScriptFrame::unchecked_code() const {
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  JSFunction* function = JSFunction::cast(this->function());
703756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  return function->unchecked_code();
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochint JavaScriptFrame::GetNumberOfIncomingArguments() const {
7088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(!SafeStackFrameIterator::is_active(isolate()) &&
7098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch         isolate()->heap()->gc_state() == Heap::NOT_IN_GC);
7108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
7118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  JSFunction* function = JSFunction::cast(this->function());
7128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return function->shared()->formal_parameter_count();
7138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
7148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
7158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
71680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenAddress JavaScriptFrame::GetCallerStackPointer() const {
7178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return fp() + StandardFrameConstants::kCallerSPOffset;
71880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
71980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
72080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(functions->length() == 0);
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  functions->Add(JSFunction::cast(function()));
724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(functions->length() == 0);
7298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Code* code_pointer = LookupCode();
730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int offset = static_cast<int>(pc() - code_pointer->address());
731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  FrameSummary summary(receiver(),
732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       JSFunction::cast(function()),
733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       code_pointer,
734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       offset,
735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                       IsConstructor());
736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  functions->Add(summary);
737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid JavaScriptFrame::PrintTop(FILE* file,
7413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               bool print_args,
7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               bool print_line_number) {
7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // constructor calls
7443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  HandleScope scope;
7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  AssertNoAllocation no_allocation;
7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JavaScriptFrameIterator it;
7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (!it.done()) {
7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (it.frame()->is_java_script()) {
7493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      JavaScriptFrame* frame = it.frame();
7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (frame->IsConstructor()) PrintF(file, "new ");
7513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // function name
7523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Object* maybe_fun = frame->function();
7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (maybe_fun->IsJSFunction()) {
7543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        JSFunction* fun = JSFunction::cast(maybe_fun);
7553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        fun->PrintName();
7563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Code* js_code = frame->unchecked_code();
7573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        Address pc = frame->pc();
7583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        int code_offset =
7593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            static_cast<int>(pc - js_code->instruction_start());
7603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF("+%d", code_offset);
7613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        SharedFunctionInfo* shared = fun->shared();
7623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        if (print_line_number) {
7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Code* code = Code::cast(
7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              v8::internal::Isolate::Current()->heap()->FindCodeObject(pc));
7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          int source_pos = code->SourcePosition(pc);
7663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          Object* maybe_script = shared->script();
7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          if (maybe_script->IsScript()) {
7683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Handle<Script> script(Script::cast(maybe_script));
7693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            int line = GetScriptLineNumberSafe(script, source_pos) + 1;
7703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            Object* script_name_raw = script->name();
7713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            if (script_name_raw->IsString()) {
7723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              String* script_name = String::cast(script->name());
7733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              SmartArrayPointer<char> c_script_name =
7743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                  script_name->ToCString(DISALLOW_NULLS,
7753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         ROBUST_STRING_TRAVERSAL);
7763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              PrintF(file, " at %s:%d", *c_script_name, line);
7773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            } else {
7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch              PrintF(file, "at <unknown>:%d", line);
7793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            }
7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          } else {
7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch            PrintF(file, " at <unknown>:<unknown>");
7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          }
7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      } else {
7853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF("<unknown>");
7863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
7873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
7883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      if (print_args) {
7893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // function arguments
7903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // (we are intentionally only printing the actually
7913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        // supplied parameters, not all parameters required)
7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF(file, "(this=");
7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        frame->receiver()->ShortPrint(file);
7943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        const int length = frame->ComputeParametersCount();
7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        for (int i = 0; i < length; i++) {
7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          PrintF(file, ", ");
7973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch          frame->GetParameter(i)->ShortPrint(file);
7983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        }
7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        PrintF(file, ")");
8003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      }
8013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      break;
8023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    }
8033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    it.Advance();
8043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
8063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid FrameSummary::Print() {
809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("receiver: ");
810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  receiver_->ShortPrint();
811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("\nfunction: ");
812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  function_->shared()->DebugName()->ShortPrint();
813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("\ncode: ");
814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  code_->ShortPrint();
815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("\npc: %d\n", offset_);
818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid OptimizedFrame::Summarize(List<FrameSummary>* frames) {
822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(frames->length() == 0);
823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(is_optimized());
824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int deopt_index = Safepoint::kNoDeoptimizationIndex;
826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // BUG(3243555): Since we don't have a lazy-deopt registered at
829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // throw-statements, we can't use the translation at the call-site of
830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // throw. An entry with no deoptimization index indicates a call-site
831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // without a lazy-deopt. As a consequence we are not allowed to inline
832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // functions containing throw.
833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JavaScriptFrame::Summarize(frames);
835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TranslationIterator it(data->TranslationByteArray(),
839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                         data->TranslationIndex(deopt_index)->value());
840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(opcode == Translation::BEGIN);
8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  it.Next();  // Drop frame count.
8433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int jsframe_count = it.Next();
844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We create the summary in reverse order because the frames
846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // in the deoptimization translation are ordered bottom-to-top.
8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  bool is_constructor = IsConstructor();
8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int i = jsframe_count;
849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (i > 0) {
850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    opcode = static_cast<Translation::Opcode>(it.Next());
8513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (opcode == Translation::JS_FRAME) {
852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      i--;
853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int ast_id = it.Next();
854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int function_id = it.Next();
855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      it.Next();  // Skip height.
856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      JSFunction* function =
857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          JSFunction::cast(data->LiteralArray()->get(function_id));
858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // The translation commands are ordered and the receiver is always
860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // at the first position. Since we are always at a call when we need
861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // to construct a stack trace, the receiver is always in a stack slot.
862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      opcode = static_cast<Translation::Opcode>(it.Next());
863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      ASSERT(opcode == Translation::STACK_SLOT ||
864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch             opcode == Translation::LITERAL);
865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      int index = it.Next();
866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Get the correct receiver in the optimized frame.
868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Object* receiver = NULL;
869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      if (opcode == Translation::LITERAL) {
870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        receiver = data->LiteralArray()->get(index);
871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // Positive index means the value is spilled to the locals
873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // area. Negative means it is stored in the incoming parameter
874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        // area.
875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        if (index >= 0) {
876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          receiver = GetExpression(index);
877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        } else {
878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          // Index -1 overlaps with last parameter, -n with the first parameter,
879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          // (-n - 1) with the receiver with n being the number of parameters
880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          // of the outermost, optimized frame.
881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          int parameter_count = ComputeParametersCount();
882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          int parameter_index = index + parameter_count;
883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch          receiver = (parameter_index == -1)
884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              ? this->receiver()
885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch              : this->GetParameter(parameter_index);
886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch        }
887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Code* code = function->shared()->code();
890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      DeoptimizationOutputData* output_data =
891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          DeoptimizationOutputData::cast(code->deoptimization_data());
892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      unsigned entry = Deoptimizer::GetOutputInfo(output_data,
893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  ast_id,
894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  function->shared());
895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      unsigned pc_offset =
896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(pc_offset > 0);
898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      frames->Add(summary);
9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      is_constructor = false;
9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    } else if (opcode == Translation::CONSTRUCT_STUB_FRAME) {
9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      // The next encountered JS_FRAME will be marked as a constructor call.
9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      it.Skip(Translation::NumberOfOperandsFor(opcode));
9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      ASSERT(!is_constructor);
9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      is_constructor = true;
907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Skip over operands to advance to the next opcode.
909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      it.Skip(Translation::NumberOfOperandsFor(opcode));
910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(!is_constructor);
913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochDeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int* deopt_index) {
918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(is_optimized());
919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  JSFunction* opt_function = JSFunction::cast(function());
921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Code* code = opt_function->code();
922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The code object may have been replaced by lazy deoptimization. Fall
924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // back to a slow search in this case to find the original optimized
925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // code object.
926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!code->contains(pc())) {
9273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    code = isolate()->inner_pointer_to_code_cache()->
9283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        GcSafeFindCodeForInnerPointer(pc());
929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(code != NULL);
931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
933b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  SafepointEntry safepoint_entry = code->GetSafepointEntry(pc());
934b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch  *deopt_index = safepoint_entry.deoptimization_index();
9351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(*deopt_index != Safepoint::kNoDeoptimizationIndex);
936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return DeoptimizationInputData::cast(code->deoptimization_data());
938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
9413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochint OptimizedFrame::GetInlineCount() {
9423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(is_optimized());
9433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  int deopt_index = Safepoint::kNoDeoptimizationIndex;
9453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
9463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  TranslationIterator it(data->TranslationByteArray(),
9483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch                         data->TranslationIndex(deopt_index)->value());
9493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
9503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  ASSERT(opcode == Translation::BEGIN);
9513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  USE(opcode);
9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  it.Next();  // Drop frame count.
9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int jsframe_count = it.Next();
9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return jsframe_count;
9553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
9563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
9573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(functions->length() == 0);
960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(is_optimized());
961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
9621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int deopt_index = Safepoint::kNoDeoptimizationIndex;
963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TranslationIterator it(data->TranslationByteArray(),
966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                         data->TranslationIndex(deopt_index)->value());
967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(opcode == Translation::BEGIN);
9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  it.Next();  // Drop frame count.
9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int jsframe_count = it.Next();
971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We insert the frames in reverse order because the frames
973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // in the deoptimization translation are ordered bottom-to-top.
9743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  while (jsframe_count > 0) {
975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    opcode = static_cast<Translation::Opcode>(it.Next());
9763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (opcode == Translation::JS_FRAME) {
9773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      jsframe_count--;
978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      it.Next();  // Skip ast id.
979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int function_id = it.Next();
980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      it.Next();  // Skip height.
981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      JSFunction* function =
982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          JSFunction::cast(data->LiteralArray()->get(function_id));
983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      functions->Add(function);
984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    } else {
985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Skip over operands to advance to the next opcode.
986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      it.Skip(Translation::NumberOfOperandsFor(opcode));
987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
9923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochint ArgumentsAdaptorFrame::GetNumberOfIncomingArguments() const {
9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return Smi::cast(GetExpression(0))->value();
9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
9953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
9963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
99780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenAddress ArgumentsAdaptorFrame::GetCallerStackPointer() const {
9988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return fp() + StandardFrameConstants::kCallerSPOffset;
99980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
100080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
100180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
100280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian MonsenAddress InternalFrame::GetCallerStackPointer() const {
100380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Internal frames have no arguments. The stack pointer of the
100480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // caller is at a fixed offset from the frame pointer.
100580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return fp() + StandardFrameConstants::kCallerSPOffset;
100680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
100780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
100880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1009756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickCode* ArgumentsAdaptorFrame::unchecked_code() const {
10108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return isolate()->builtins()->builtin(
101144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Builtins::kArgumentsAdaptorTrampoline);
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1015756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain MerrickCode* InternalFrame::unchecked_code() const {
1016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int offset = InternalFrameConstants::kCodeOffset;
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* code = Memory::Object_at(fp() + offset);
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(code != NULL);
1019756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick  return reinterpret_cast<Code*>(code);
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StackFrame::PrintIndex(StringStream* accumulator,
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            PrintMode mode,
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            int index) {
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  accumulator->Add((mode == OVERVIEW) ? "%5d: " : "[%d]: ", index);
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid JavaScriptFrame::Print(StringStream* accumulator,
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            PrintMode mode,
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                            int index) const {
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HandleScope scope;
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* receiver = this->receiver();
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* function = this->function();
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  accumulator->PrintSecurityTokenIfChanged(function);
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintIndex(accumulator, mode, index);
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Code* code = NULL;
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (IsConstructor()) accumulator->Add("new ");
1041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  accumulator->PrintFunction(function, receiver, &code);
10426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Get scope information for nicer output, if possible. If code is NULL, or
10443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // doesn't contain scope info, scope_info will return 0 for the number of
10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // parameters, stack local variables, context local variables, stack slots,
10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // or context slots.
10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Handle<ScopeInfo> scope_info(ScopeInfo::Empty());
10483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch
10496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  if (function->IsJSFunction()) {
10506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Handle<SharedFunctionInfo> shared(JSFunction::cast(function)->shared());
10513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    scope_info = Handle<ScopeInfo>(shared->scope_info());
10526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    Object* script_obj = shared->script();
10536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    if (script_obj->IsScript()) {
10546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Handle<Script> script(Script::cast(script_obj));
10556ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      accumulator->Add(" [");
10566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      accumulator->PrintName(script->name());
10576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      Address pc = this->pc();
10596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      if (code != NULL && code->kind() == Code::FUNCTION &&
1060ac95265630a4e0c317a7a7201d17a57df7d9bcceLeon Clarke          pc >= code->instruction_start() && pc < code->instruction_end()) {
10616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int source_pos = code->SourcePosition(pc);
10626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int line = GetScriptLineNumberSafe(script, source_pos) + 1;
10636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        accumulator->Add(":%d", line);
10646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      } else {
10656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int function_start_pos = shared->start_position();
10666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        int line = GetScriptLineNumberSafe(script, function_start_pos) + 1;
10676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        accumulator->Add(":~%d", line);
10686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      }
10696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
10706ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      accumulator->Add("] ");
10716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    }
10726ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
10736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  accumulator->Add("(this=%o", receiver);
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print the parameters.
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int parameters_count = ComputeParametersCount();
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < parameters_count; i++) {
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add(",");
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // If we have a name for the parameter we print it. Nameless
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // parameters are either because we have more actual parameters
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // than formal parameters or because we have no scope information.
10833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (i < scope_info->ParameterCount()) {
10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      accumulator->PrintName(scope_info->ParameterName(i));
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      accumulator->Add("=");
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("%o", GetParameter(i));
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  accumulator->Add(")");
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mode == OVERVIEW) {
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("\n");
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  if (is_optimized()) {
1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    accumulator->Add(" {\n// optimized frame\n}\n");
1097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    return;
1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  }
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  accumulator->Add(" {\n");
1100a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Compute the number of locals and expression stack elements.
11023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int stack_locals_count = scope_info->StackLocalCount();
11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int heap_locals_count = scope_info->ContextLocalCount();
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int expressions_count = ComputeExpressionsCount();
1105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print stack-allocated local variables.
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (stack_locals_count > 0) {
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("  // stack-allocated locals\n");
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < stack_locals_count; i++) {
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("  var ");
11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    accumulator->PrintName(scope_info->StackLocalName(i));
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add(" = ");
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (i < expressions_count) {
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      accumulator->Add("%o", GetExpression(i));
1116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      accumulator->Add("// no expression found - inconsistent frame?");
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("\n");
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Try to get hold of the context of this frame.
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Context* context = NULL;
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (this->context() != NULL && this->context()->IsContext()) {
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    context = Context::cast(this->context());
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print heap-allocated local variables.
11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (heap_locals_count > 0) {
1130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("  // heap-allocated locals\n");
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < heap_locals_count; i++) {
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("  var ");
11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    accumulator->PrintName(scope_info->ContextLocalName(i));
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add(" = ");
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (context != NULL) {
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (i < context->length()) {
11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        accumulator->Add("%o", context->get(Context::MIN_CONTEXT_SLOTS + i));
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        accumulator->Add(
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block            "// warning: missing context slot - inconsistent frame?");
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      accumulator->Add("// warning: no context found - inconsistent frame?");
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("\n");
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print the expression stack.
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int expressions_start = stack_locals_count;
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (expressions_start < expressions_count) {
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("  // expression stack (top to bottom)\n");
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = expressions_count - 1; i >= expressions_start; i--) {
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (IsExpressionInsideHandler(i)) continue;
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("  [%02d] : %o\n", i, GetExpression(i));
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print details about the function.
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (FLAG_max_stack_trace_source_length != 0 && code != NULL) {
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    SharedFunctionInfo* shared = JSFunction::cast(function)->shared();
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("--------- s o u r c e   c o d e ---------\n");
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    shared->SourceCodePrint(accumulator, FLAG_max_stack_trace_source_length);
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("\n-----------------------------------------\n");
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  accumulator->Add("}\n\n");
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid ArgumentsAdaptorFrame::Print(StringStream* accumulator,
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  PrintMode mode,
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  int index) const {
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int actual = ComputeParametersCount();
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int expected = -1;
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object* function = this->function();
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (function->IsJSFunction()) {
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    expected = JSFunction::cast(function)->shared()->formal_parameter_count();
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  PrintIndex(accumulator, mode, index);
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  accumulator->Add("arguments adaptor frame: %d->%d", actual, expected);
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (mode == OVERVIEW) {
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("\n");
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return;
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  accumulator->Add(" {\n");
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Print actual arguments.
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (actual > 0) accumulator->Add("  // actual arguments\n");
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < actual; i++) {
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("  [%02d] : %o", i, GetParameter(i));
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (expected != -1 && i >= expected) {
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      accumulator->Add("  // not passed to callee");
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator->Add("\n");
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  accumulator->Add("}\n\n");
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid EntryFrame::Iterate(ObjectVisitor* v) const {
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackHandlerIterator it(this, top_handler());
1205a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(!it.done());
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StackHandler* handler = it.handler();
12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(handler->is_js_entry());
12088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  handler->Iterate(v, LookupCode());
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
121080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // Make sure that the entry frame does not contain more than one
121180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  // stack handler.
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  it.Advance();
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(it.done());
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
12158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  IteratePc(v, pc_address(), LookupCode());
1216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StandardFrame::IterateExpressions(ObjectVisitor* v) const {
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int offset = StandardFrameConstants::kContextOffset;
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object** base = &Memory::Object_at(sp());
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Object** limit = &Memory::Object_at(fp() + offset) + 1;
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    StackHandler* handler = it.handler();
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Traverse pointers down to - but not including - the next
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // handler in the handler chain. Update the base to skip the
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // handler and allow the handler to traverse its own pointers.
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    const Address address = handler->address();
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    v->VisitPointers(base, reinterpret_cast<Object**>(address));
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
1231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Traverse the pointers in the handler itself.
12328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    handler->Iterate(v, LookupCode());
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v->VisitPointers(base, limit);
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid JavaScriptFrame::Iterate(ObjectVisitor* v) const {
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IterateExpressions(v);
12408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  IteratePc(v, pc_address(), LookupCode());
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid InternalFrame::Iterate(ObjectVisitor* v) const {
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Internal frames only have object pointers on the expression stack
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // as they never have any arguments.
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  IterateExpressions(v);
12488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  IteratePc(v, pc_address(), LookupCode());
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockJavaScriptFrame* StackFrameLocator::FindJavaScriptFrame(int n) {
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(n >= 0);
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i <= n; i++) {
1258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    while (!iterator_.frame()->is_java_script()) iterator_.Advance();
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (i == n) return JavaScriptFrame::cast(iterator_.frame());
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    iterator_.Advance();
1261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  UNREACHABLE();
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NULL;
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// -------------------------------------------------------------------------
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic Map* GcSafeMapOfCodeSpaceObject(HeapObject* object) {
12713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  MapWord map_word = object->map_word();
12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return map_word.IsForwardingAddress() ?
12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      map_word.ToForwardingAddress()->map() : map_word.ToMap();
12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic int GcSafeSizeOfCodeSpaceObject(HeapObject* object) {
12783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return object->SizeFromMap(GcSafeMapOfCodeSpaceObject(object));
12793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG
12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool GcSafeCodeContains(HeapObject* code, Address addr) {
12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Map* map = GcSafeMapOfCodeSpaceObject(code);
12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(map == code->GetHeap()->code_map());
12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address start = code->address();
12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address end = code->address() + code->SizeFromMap(map);
12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return start <= addr && addr < end;
12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif
12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCode* InnerPointerToCodeCache::GcSafeCastToCode(HeapObject* object,
12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                Address inner_pointer) {
129580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  Code* code = reinterpret_cast<Code*>(object);
12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(code != NULL && GcSafeCodeContains(code, inner_pointer));
129780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return code;
129880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
129980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
130080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochCode* InnerPointerToCodeCache::GcSafeFindCodeForInnerPointer(
13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address inner_pointer) {
130344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Heap* heap = isolate_->heap();
13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Check if the inner pointer points into a large object chunk.
13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  LargePage* large_page = heap->lo_space()->FindPage(inner_pointer);
13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (large_page != NULL) {
13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    return GcSafeCastToCode(large_page->GetObject(), inner_pointer);
13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Iterate through the page until we reach the end or find an object starting
13113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // after the inner pointer.
13123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Page* page = Page::FromAddress(inner_pointer);
13133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address addr = page->skip_list()->StartFor(inner_pointer);
13153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address top = heap->code_space()->top();
13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Address limit = heap->code_space()->limit();
13183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
131980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  while (true) {
13203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (addr == top && addr != limit) {
13213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      addr = limit;
13223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      continue;
132380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    }
13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    HeapObject* obj = HeapObject::FromAddress(addr);
13263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    int obj_size = GcSafeSizeOfCodeSpaceObject(obj);
13273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    Address next_addr = addr + obj_size;
13283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    if (next_addr > inner_pointer) return GcSafeCastToCode(obj, inner_pointer);
13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    addr = next_addr;
133080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
133180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
133280d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochInnerPointerToCodeCache::InnerPointerToCodeCacheEntry*
13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    InnerPointerToCodeCache::GetCacheEntry(Address inner_pointer) {
133644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate_->counters()->pc_to_code()->Increment();
13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(IsPowerOf2(kInnerPointerToCodeCacheSize));
133880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  uint32_t hash = ComputeIntegerHash(
13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      static_cast<uint32_t>(reinterpret_cast<uintptr_t>(inner_pointer)),
1340c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch      v8::internal::kZeroHashSeed);
13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  uint32_t index = hash & (kInnerPointerToCodeCacheSize - 1);
13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  InnerPointerToCodeCacheEntry* entry = cache(index);
13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (entry->inner_pointer == inner_pointer) {
134444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    isolate_->counters()->pc_to_code_cached()->Increment();
13453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    ASSERT(entry->code == GcSafeFindCodeForInnerPointer(inner_pointer));
134680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  } else {
134780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // Because this code may be interrupted by a profiling signal that
13483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // also queries the cache, we cannot update inner_pointer before the code
13493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // has been set. Otherwise, we risk trying to use a cache entry before
135080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen    // the code has been computed.
13513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    entry->code = GcSafeFindCodeForInnerPointer(inner_pointer);
1352b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch    entry->safepoint_entry.Reset();
13533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    entry->inner_pointer = inner_pointer;
135480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  }
135580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen  return entry;
135680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen}
135780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
135880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
135980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen// -------------------------------------------------------------------------
136080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockint NumRegs(RegList reglist) {
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int n = 0;
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  while (reglist != 0) {
1364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    n++;
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    reglist &= reglist - 1;  // clear one bit
1366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return n;
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
137144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockstruct JSCallerSavedCodeData {
137244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  JSCallerSavedCodeData() {
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int i = 0;
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int r = 0; r < kNumRegs; r++)
1375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if ((kJSCallerSaved & (1 << r)) != 0)
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        reg_code[i++] = r;
1377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ASSERT(i == kNumJSCallerSaved);
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
138044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int reg_code[kNumJSCallerSaved];
138144f0eee88ff00398ff7f715fab053374d808c90dSteve Block};
138244f0eee88ff00398ff7f715fab053374d808c90dSteve Block
138344f0eee88ff00398ff7f715fab053374d808c90dSteve Block
13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic LazyInstance<JSCallerSavedCodeData>::type caller_saved_code_data =
13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    LAZY_INSTANCE_INITIALIZER;
138644f0eee88ff00398ff7f715fab053374d808c90dSteve Block
138744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint JSCallerSavedCode(int n) {
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ASSERT(0 <= n && n < kNumJSCallerSaved);
13893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  return caller_saved_code_data.Get().reg_code[n];
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13936ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#define DEFINE_WRAPPER(type, field)                              \
13946ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockclass field##_Wrapper : public ZoneObject {                      \
13956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block public:  /* NOLINT */                                           \
13966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  field##_Wrapper(const field& original) : frame_(original) {    \
13976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }                                                              \
13986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  field frame_;                                                  \
13996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block};
14006ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockSTACK_FRAME_TYPE_LIST(DEFINE_WRAPPER)
14016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#undef DEFINE_WRAPPER
14026ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14036ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic StackFrame* AllocateFrameCopy(StackFrame* frame) {
14046ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#define FRAME_TYPE_CASE(type, field) \
14056ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  case StackFrame::type: { \
14066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    field##_Wrapper* wrapper = \
14076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block        new field##_Wrapper(*(reinterpret_cast<field*>(frame))); \
14086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    return &wrapper->frame_; \
14096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  switch (frame->type()) {
14126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    STACK_FRAME_TYPE_LIST(FRAME_TYPE_CASE)
14136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    default: UNREACHABLE();
14146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#undef FRAME_TYPE_CASE
14166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return NULL;
14176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14196ded16be15dd865a9b21ea304d5273c8be299c87Steve BlockVector<StackFrame*> CreateStackMap() {
14206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  ZoneList<StackFrame*> list(10);
14216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  for (StackFrameIterator it; !it.done(); it.Advance()) {
14226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    StackFrame* frame = AllocateFrameCopy(it.frame());
14236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    list.Add(frame);
14246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  }
14256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  return list.ToVector();
14266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block}
14276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
14286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
1430