deoptimizer.cc revision 8b112d2025046f85ef7f6be087c6129c872ebad2
1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2010 the V8 project authors. All rights reserved.
2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Redistribution and use in source and binary forms, with or without
3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// modification, are permitted provided that the following conditions are
4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// met:
5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//
6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Redistributions of source code must retain the above copyright
7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       notice, this list of conditions and the following disclaimer.
8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Redistributions in binary form must reproduce the above
9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       copyright notice, this list of conditions and the following
10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       disclaimer in the documentation and/or other materials provided
11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       with the distribution.
12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//     * Neither the name of Google Inc. nor the names of its
13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       contributors may be used to endorse or promote products derived
14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//       from this software without specific prior written permission.
15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch//
16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "v8.h"
29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "codegen.h"
31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h"
32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "disasm.h"
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "global-handles.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "macro-assembler.h"
36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "prettyprinter.h"
37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 {
40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal {
41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockDeoptimizerData::DeoptimizerData() {
4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  eager_deoptimization_entry_code_ = NULL;
4444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  lazy_deoptimization_entry_code_ = NULL;
4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  current_ = NULL;
4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  deoptimizing_code_list_ = NULL;
4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
5044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockDeoptimizerData::~DeoptimizerData() {
5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (eager_deoptimization_entry_code_ != NULL) {
5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    eager_deoptimization_entry_code_->Free(EXECUTABLE);
5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    eager_deoptimization_entry_code_ = NULL;
5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (lazy_deoptimization_entry_code_ != NULL) {
5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lazy_deoptimization_entry_code_->Free(EXECUTABLE);
5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    lazy_deoptimization_entry_code_ = NULL;
5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochDeoptimizer* Deoptimizer::New(JSFunction* function,
62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              BailoutType type,
63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              unsigned bailout_id,
64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                              Address from,
6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              int fp_to_sp_delta,
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                              Isolate* isolate) {
6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(isolate == Isolate::Current());
6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Deoptimizer* deoptimizer = new Deoptimizer(isolate,
6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             function,
7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             type,
7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             bailout_id,
7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             from,
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block                                             fp_to_sp_delta);
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(isolate->deoptimizer_data()->current_ == NULL);
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->deoptimizer_data()->current_ = deoptimizer;
76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return deoptimizer;
77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockDeoptimizer* Deoptimizer::Grab(Isolate* isolate) {
8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(isolate == Isolate::Current());
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Deoptimizer* result = isolate->deoptimizer_data()->current_;
83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(result != NULL);
84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  result->DeleteFrameDescriptions();
8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  isolate->deoptimizer_data()->current_ = NULL;
86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm,
91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                int count,
92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                BailoutType type) {
93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TableEntryGenerator generator(masm, type, count);
94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  generator.Generate();
95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass DeoptimizingVisitor : public OptimizedFunctionVisitor {
99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public:
100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void EnterContext(Context* context) {
101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (FLAG_trace_deopt) {
102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      PrintF("[deoptimize context: %" V8PRIxPTR "]\n",
103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch             reinterpret_cast<intptr_t>(context));
104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void VisitFunction(JSFunction* function) {
108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Deoptimizer::DeoptimizeFunction(function);
109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  virtual void LeaveContext(Context* context) {
112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    context->ClearOptimizedFunctions();
113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch};
115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DeoptimizeAll() {
118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_allocation;
119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_deopt) {
121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("[deoptimize all contexts]\n");
122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizingVisitor visitor;
125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitAllOptimizedFunctions(&visitor);
126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DeoptimizeGlobalObject(JSObject* object) {
130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_allocation;
131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizingVisitor visitor;
133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  VisitAllOptimizedFunctionsForGlobalObject(object, &visitor);
134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::VisitAllOptimizedFunctionsForContext(
138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Context* context, OptimizedFunctionVisitor* visitor) {
139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_allocation;
140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(context->IsGlobalContext());
142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  visitor->EnterContext(context);
144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Run through the list of optimized functions and deoptimize them.
145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Object* element = context->OptimizedFunctionsListHead();
146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!element->IsUndefined()) {
147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JSFunction* element_function = JSFunction::cast(element);
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Get the next link before deoptimizing as deoptimizing will clear the
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // next link.
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    element = element_function->next_function_link();
151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    visitor->VisitFunction(element_function);
152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  visitor->LeaveContext(context);
154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::VisitAllOptimizedFunctionsForGlobalObject(
158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JSObject* object, OptimizedFunctionVisitor* visitor) {
159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_allocation;
160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (object->IsJSGlobalProxy()) {
162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    Object* proto = object->GetPrototype();
163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(proto->IsJSGlobalObject());
164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitAllOptimizedFunctionsForContext(
165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        GlobalObject::cast(proto)->global_context(), visitor);
166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (object->IsGlobalObject()) {
167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitAllOptimizedFunctionsForContext(
168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        GlobalObject::cast(object)->global_context(), visitor);
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::VisitAllOptimizedFunctions(
174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    OptimizedFunctionVisitor* visitor) {
175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  AssertNoAllocation no_allocation;
176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Run through the list of all global contexts and deoptimize.
17844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Object* global = Isolate::Current()->heap()->global_contexts_list();
179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (!global->IsUndefined()) {
180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    VisitAllOptimizedFunctionsForGlobalObject(Context::cast(global)->global(),
181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                              visitor);
182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    global = Context::cast(global)->get(Context::NEXT_CONTEXT_LINK);
183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::HandleWeakDeoptimizedCode(
188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    v8::Persistent<v8::Value> obj, void* data) {
189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizingCodeListNode* node =
190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      reinterpret_cast<DeoptimizingCodeListNode*>(data);
191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  RemoveDeoptimizingCode(*node->code());
192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  node = Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_;
194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (node != NULL) {
195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(node != reinterpret_cast<DeoptimizingCodeListNode*>(data));
196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    node = node->next();
197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
2028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) {
203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  deoptimizer->DoComputeOutputFrames();
204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
20744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockDeoptimizer::Deoptimizer(Isolate* isolate,
20844f0eee88ff00398ff7f715fab053374d808c90dSteve Block                         JSFunction* function,
209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                         BailoutType type,
210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                         unsigned bailout_id,
211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                         Address from,
212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                         int fp_to_sp_delta)
21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    : isolate_(isolate),
21444f0eee88ff00398ff7f715fab053374d808c90dSteve Block      function_(function),
215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bailout_id_(bailout_id),
216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bailout_type_(type),
217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      from_(from),
218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      fp_to_sp_delta_(fp_to_sp_delta),
219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output_count_(0),
220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output_(NULL),
2218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      deferred_heap_numbers_(0) {
222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_deopt && type != OSR) {
223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("**** DEOPT: ");
224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function->PrintName();
225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n",
226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           bailout_id,
227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           reinterpret_cast<intptr_t>(from),
228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           fp_to_sp_delta - (2 * kPointerSize));
229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (FLAG_trace_osr && type == OSR) {
230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("**** OSR: ");
231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function->PrintName();
232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF(" at ast id #%u, address 0x%" V8PRIxPTR ", frame size %d\n",
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           bailout_id,
234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           reinterpret_cast<intptr_t>(from),
235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           fp_to_sp_delta - (2 * kPointerSize));
236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Find the optimized code.
238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (type == EAGER) {
239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(from == NULL);
240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    optimized_code_ = function_->code();
241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (type == LAZY) {
242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    optimized_code_ = FindDeoptimizingCodeFromAddress(from);
243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(optimized_code_ != NULL);
244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else if (type == OSR) {
245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // The function has already been optimized and we're transitioning
246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // from the unoptimized shared version to the optimized one in the
247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // function. The return address (from) points to unoptimized code.
248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    optimized_code_ = function_->code();
249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION);
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(!optimized_code_->contains(from));
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
25244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(HEAP->allow_allocation(false));
253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned size = ComputeInputFrameSize();
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  input_ = new(size) FrameDescription(size, function);
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochDeoptimizer::~Deoptimizer() {
259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(input_ == NULL && output_ == NULL);
260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DeleteFrameDescriptions() {
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  delete input_;
265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < output_count_; ++i) {
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (output_[i] != input_) delete output_[i];
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  delete[] output_;
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  input_ = NULL;
270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  output_ = NULL;
27144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(!HEAP->allow_allocation(true));
272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAddress Deoptimizer::GetDeoptimizationEntry(int id, BailoutType type) {
276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(id >= 0);
277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (id >= kNumberOfEntries) return NULL;
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LargeObjectChunk* base = NULL;
27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DeoptimizerData* data = Isolate::Current()->deoptimizer_data();
280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (type == EAGER) {
28144f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (data->eager_deoptimization_entry_code_ == NULL) {
28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      data->eager_deoptimization_entry_code_ = CreateCode(type);
283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
28444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    base = data->eager_deoptimization_entry_code_;
285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
28644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    if (data->lazy_deoptimization_entry_code_ == NULL) {
28744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      data->lazy_deoptimization_entry_code_ = CreateCode(type);
288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    base = data->lazy_deoptimization_entry_code_;
290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return
292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      static_cast<Address>(base->GetStartAddress()) + (id * table_entry_size_);
293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint Deoptimizer::GetDeoptimizationId(Address addr, BailoutType type) {
297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LargeObjectChunk* base = NULL;
29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DeoptimizerData* data = Isolate::Current()->deoptimizer_data();
299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (type == EAGER) {
30044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    base = data->eager_deoptimization_entry_code_;
301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    base = data->lazy_deoptimization_entry_code_;
303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (base == NULL ||
305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      addr < base->GetStartAddress() ||
306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      addr >= base->GetStartAddress() +
307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          (kNumberOfEntries * table_entry_size_)) {
308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return kNotDeoptimizationEntry;
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT_EQ(0,
311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      static_cast<int>(addr - base->GetStartAddress()) % table_entry_size_);
312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return static_cast<int>(addr - base->GetStartAddress()) / table_entry_size_;
313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockint Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data,
3179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                               unsigned id,
3189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block                               SharedFunctionInfo* shared) {
319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // TODO(kasperl): For now, we do a simple linear search for the PC
320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // offset associated with the given node id. This should probably be
321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // changed to a binary search.
322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = data->DeoptPoints();
323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Smi* smi_id = Smi::FromInt(id);
324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < length; i++) {
325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (data->AstId(i) == smi_id) {
326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return data->PcAndState(i)->value();
327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("[couldn't find pc offset for node=%u]\n", id);
330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("[method: %s]\n", *shared->DebugName()->ToCString());
331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Print the source code if available.
332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  HeapStringAllocator string_allocator;
333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  StringStream stream(&string_allocator);
334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  shared->SourceCodePrint(&stream, -1);
335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  PrintF("[source:\n%s\n]", *stream.ToCString());
336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();
338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return -1;
339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
34244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) {
343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = 0;
34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DeoptimizingCodeListNode* node =
34544f0eee88ff00398ff7f715fab053374d808c90dSteve Block      isolate->deoptimizer_data()->deoptimizing_code_list_;
346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (node != NULL) {
347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    length++;
348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    node = node->next();
349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return length;
351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DoComputeOutputFrames() {
355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (bailout_type_ == OSR) {
356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    DoComputeOsrOutputFrame();
357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return;
358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Print some helpful diagnostic information.
361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int64_t start = OS::Ticks();
362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_deopt) {
363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("[deoptimizing%s: begin 0x%08" V8PRIxPTR " ",
364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           (bailout_type_ == LAZY ? " (lazy)" : ""),
365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           reinterpret_cast<intptr_t>(function_));
366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function_->PrintName();
367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF(" @%d]\n", bailout_id_);
368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Determine basic deoptimization information.  The optimized frame is
371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // described by the input data.
372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizationInputData* input_data =
373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      DeoptimizationInputData::cast(optimized_code_->deoptimization_data());
374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned node_id = input_data->AstId(bailout_id_)->value();
375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ByteArray* translations = input_data->TranslationByteArray();
376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned translation_index =
377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      input_data->TranslationIndex(bailout_id_)->value();
378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Do the input frame to output frame(s) translation.
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  TranslationIterator iterator(translations, translation_index);
381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Translation::Opcode opcode =
382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      static_cast<Translation::Opcode>(iterator.Next());
383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(Translation::BEGIN == opcode);
384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  USE(opcode);
385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Read the number of output frames and allocate an array for their
386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // descriptions.
387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int count = iterator.Next();
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(output_ == NULL);
389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  output_ = new FrameDescription*[count];
390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < count; ++i) {
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    output_[i] = NULL;
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  output_count_ = count;
394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Translate each output frame.
396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < count; ++i) {
397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    DoComputeFrame(&iterator, i);
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Print some helpful diagnostic information.
401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (FLAG_trace_deopt) {
402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    double ms = static_cast<double>(OS::Ticks() - start) / 1000;
403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int index = output_count_ - 1;  // Index of the topmost frame.
404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    JSFunction* function = output_[index]->GetFunction();
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF("[deoptimizing: end 0x%08" V8PRIxPTR " ",
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           reinterpret_cast<intptr_t>(function));
407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    function->PrintName();
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    PrintF(" => node=%u, pc=0x%08" V8PRIxPTR ", state=%s, took %0.3f ms]\n",
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           node_id,
410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           output_[index]->GetPc(),
411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           FullCodeGenerator::State2String(
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               static_cast<FullCodeGenerator::State>(
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                   output_[index]->GetState()->value())),
414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch           ms);
415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid Deoptimizer::MaterializeHeapNumbers() {
4208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  for (int i = 0; i < deferred_heap_numbers_.length(); i++) {
4218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i];
4228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Handle<Object> num = isolate_->factory()->NewNumber(d.value());
4238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (FLAG_trace_deopt) {
4248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      PrintF("Materializing a new heap number %p [%e] in slot %p\n",
4258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             reinterpret_cast<void*>(*num),
4268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             d.value(),
4278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch             d.slot_address());
4288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    Memory::Object_at(d.slot_address()) = *num;
431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DoTranslateCommand(TranslationIterator* iterator,
436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     int frame_index,
437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                     unsigned output_offset) {
438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  disasm::NameConverter converter;
439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // A GC-safe temporary placeholder that we can put in the output frame.
440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0));
441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Ignore commands marked as duplicate and act on the first non-duplicate.
443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Translation::Opcode opcode =
444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      static_cast<Translation::Opcode>(iterator->Next());
445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (opcode == Translation::DUPLICATE) {
446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    opcode = static_cast<Translation::Opcode>(iterator->Next());
447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    iterator->Skip(Translation::NumberOfOperandsFor(opcode));
448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    opcode = static_cast<Translation::Opcode>(iterator->Next());
449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (opcode) {
452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::BEGIN:
453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::FRAME:
454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::DUPLICATE:
455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNREACHABLE();
456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::REGISTER: {
459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int input_reg = iterator->Next();
460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      intptr_t input_value = input_->GetRegister(input_reg);
461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_deopt) {
462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF(
463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            "    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s\n",
464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            output_[frame_index]->GetTop() + output_offset,
465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            output_offset,
466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            input_value,
467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            converter.NameOfCPURegister(input_reg));
468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output_[frame_index]->SetFrameSlot(output_offset, input_value);
470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::INT32_REGISTER: {
474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int input_reg = iterator->Next();
475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      intptr_t value = input_->GetRegister(input_reg);
476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool is_smi = Smi::IsValid(value);
477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_deopt) {
478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF(
479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            "    0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n",
480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            output_[frame_index]->GetTop() + output_offset,
481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            output_offset,
482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            value,
483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            converter.NameOfCPURegister(input_reg),
484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            is_smi ? "smi" : "heap number");
485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (is_smi) {
487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        intptr_t tagged_value =
488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // We save the untagged value on the side and store a GC-safe
492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // temporary placeholder in the frame.
4938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
4948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                       static_cast<double>(static_cast<int32_t>(value)));
495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::DOUBLE_REGISTER: {
501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int input_reg = iterator->Next();
502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      double value = input_->GetDoubleRegister(input_reg);
503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_deopt) {
504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- %e ; %s\n",
505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_[frame_index]->GetTop() + output_offset,
506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_offset,
507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value,
508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               DoubleRegister::AllocationIndexToString(input_reg));
509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // We save the untagged value on the side and store a GC-safe
511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // temporary placeholder in the frame.
5128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::STACK_SLOT: {
518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int input_slot_index = iterator->Next();
519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      unsigned input_offset =
520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          input_->GetOffsetFromSlotIndex(this, input_slot_index);
521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      intptr_t input_value = input_->GetFrameSlot(input_offset);
522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_deopt) {
523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("    0x%08" V8PRIxPTR ": ",
524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_[frame_index]->GetTop() + output_offset);
525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d]\n",
526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_offset,
527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               input_value,
528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               input_offset);
529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output_[frame_index]->SetFrameSlot(output_offset, input_value);
531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::INT32_STACK_SLOT: {
535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int input_slot_index = iterator->Next();
536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      unsigned input_offset =
537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          input_->GetOffsetFromSlotIndex(this, input_slot_index);
538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      intptr_t value = input_->GetFrameSlot(input_offset);
539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      bool is_smi = Smi::IsValid(value);
540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_deopt) {
541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("    0x%08" V8PRIxPTR ": ",
542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_[frame_index]->GetTop() + output_offset);
543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("[top + %d] <- %" V8PRIdPTR " ; [esp + %d] (%s)\n",
544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_offset,
545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value,
546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               input_offset,
547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               is_smi ? "smi" : "heap number");
548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (is_smi) {
550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        intptr_t tagged_value =
551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch            reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value)));
552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        output_[frame_index]->SetFrameSlot(output_offset, tagged_value);
553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // We save the untagged value on the side and store a GC-safe
555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        // temporary placeholder in the frame.
5568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        AddDoubleValue(output_[frame_index]->GetTop() + output_offset,
5578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                       static_cast<double>(static_cast<int32_t>(value)));
558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::DOUBLE_STACK_SLOT: {
564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int input_slot_index = iterator->Next();
565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      unsigned input_offset =
566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          input_->GetOffsetFromSlotIndex(this, input_slot_index);
567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      double value = input_->GetDoubleFrameSlot(input_offset);
568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_deopt) {
569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- %e ; [esp + %d]\n",
570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_[frame_index]->GetTop() + output_offset,
571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_offset,
572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               value,
573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               input_offset);
574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // We save the untagged value on the side and store a GC-safe
576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // temporary placeholder in the frame.
5778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value);
578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder);
579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::LITERAL: {
583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      Object* literal = ComputeLiteral(iterator->Next());
584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_deopt) {
585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- ",
586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_[frame_index]->GetTop() + output_offset,
587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_offset);
588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        literal->ShortPrint();
589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF(" ; literal\n");
590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      intptr_t value = reinterpret_cast<intptr_t>(literal);
592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output_[frame_index]->SetFrameSlot(output_offset, value);
593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::ARGUMENTS_OBJECT: {
597086aeeaae12517475c22695a200be45495516549Ben Murdoch      // Use the arguments marker value as a sentinel and fill in the arguments
598086aeeaae12517475c22695a200be45495516549Ben Murdoch      // object after the deoptimized frame is built.
599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      ASSERT(frame_index == 0);  // Only supported for first frame.
600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_deopt) {
601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- ",
602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_[frame_index]->GetTop() + output_offset,
603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_offset);
60444f0eee88ff00398ff7f715fab053374d808c90dSteve Block        isolate_->heap()->arguments_marker()->ShortPrint();
605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        PrintF(" ; arguments object\n");
606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
60744f0eee88ff00398ff7f715fab053374d808c90dSteve Block      intptr_t value = reinterpret_cast<intptr_t>(
60844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          isolate_->heap()->arguments_marker());
609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output_[frame_index]->SetFrameSlot(output_offset, value);
610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator,
617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                        int* input_offset) {
618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  disasm::NameConverter converter;
619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  FrameDescription* output = output_[0];
620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The input values are all part of the unoptimized frame so they
622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // are all tagged pointers.
623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uintptr_t input_value = input_->GetFrameSlot(*input_offset);
624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Object* input_object = reinterpret_cast<Object*>(input_value);
625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Translation::Opcode opcode =
627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      static_cast<Translation::Opcode>(iterator->Next());
628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool duplicate = (opcode == Translation::DUPLICATE);
629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (duplicate) {
630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    opcode = static_cast<Translation::Opcode>(iterator->Next());
631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (opcode) {
634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::BEGIN:
635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::FRAME:
636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::DUPLICATE:
637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNREACHABLE();  // Malformed input.
638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       return false;
639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch     case Translation::REGISTER: {
641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       int output_reg = iterator->Next();
642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       if (FLAG_trace_osr) {
6431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block         PrintF("    %s <- 0x%08" V8PRIxPTR " ; [sp + %d]\n",
644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                converter.NameOfCPURegister(output_reg),
645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                input_value,
646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                *input_offset);
647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       }
648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       output->SetRegister(output_reg, input_value);
649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch       break;
650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch     }
651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::INT32_REGISTER: {
653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Abort OSR if we don't have a number.
654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!input_object->IsNumber()) return false;
655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int output_reg = iterator->Next();
657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int int32_value = input_object->IsSmi()
658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          ? Smi::cast(input_object)->value()
659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          : FastD2I(input_object->Number());
660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Abort the translation if the conversion lost information.
661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!input_object->IsSmi() &&
662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          FastI2D(int32_value) != input_object->Number()) {
663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (FLAG_trace_osr) {
664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          PrintF("**** %g could not be converted to int32 ****\n",
665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 input_object->Number());
666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return false;
668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_osr) {
6701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PrintF("    %s <- %d (int32) ; [sp + %d]\n",
671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               converter.NameOfCPURegister(output_reg),
672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               int32_value,
673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               *input_offset);
674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output->SetRegister(output_reg, int32_value);
676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::DOUBLE_REGISTER: {
680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Abort OSR if we don't have a number.
681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!input_object->IsNumber()) return false;
682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int output_reg = iterator->Next();
684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      double double_value = input_object->Number();
685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_osr) {
6861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PrintF("    %s <- %g (double) ; [sp + %d]\n",
687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               DoubleRegister::AllocationIndexToString(output_reg),
688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               double_value,
689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               *input_offset);
690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output->SetDoubleRegister(output_reg, double_value);
692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::STACK_SLOT: {
696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int output_index = iterator->Next();
697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      unsigned output_offset =
698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          output->GetOffsetFromSlotIndex(this, output_index);
699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_osr) {
7001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PrintF("    [sp + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d]\n",
701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_offset,
702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               input_value,
703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               *input_offset);
704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output->SetFrameSlot(output_offset, input_value);
706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::INT32_STACK_SLOT: {
710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Abort OSR if we don't have a number.
711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!input_object->IsNumber()) return false;
712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int output_index = iterator->Next();
714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      unsigned output_offset =
715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          output->GetOffsetFromSlotIndex(this, output_index);
716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int int32_value = input_object->IsSmi()
717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          ? Smi::cast(input_object)->value()
718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          : DoubleToInt32(input_object->Number());
719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Abort the translation if the conversion lost information.
720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!input_object->IsSmi() &&
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          FastI2D(int32_value) != input_object->Number()) {
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        if (FLAG_trace_osr) {
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          PrintF("**** %g could not be converted to int32 ****\n",
724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                 input_object->Number());
725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        }
726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        return false;
727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_osr) {
7291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PrintF("    [sp + %d] <- %d (int32) ; [sp + %d]\n",
730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_offset,
731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               int32_value,
732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               *input_offset);
733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output->SetFrameSlot(output_offset, int32_value);
735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::DOUBLE_STACK_SLOT: {
739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      static const int kLowerOffset = 0 * kPointerSize;
740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      static const int kUpperOffset = 1 * kPointerSize;
741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Abort OSR if we don't have a number.
743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (!input_object->IsNumber()) return false;
744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int output_index = iterator->Next();
746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      unsigned output_offset =
747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch          output->GetOffsetFromSlotIndex(this, output_index);
748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      double double_value = input_object->Number();
749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      uint64_t int_value = BitCast<uint64_t, double>(double_value);
750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int32_t lower = static_cast<int32_t>(int_value);
751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      int32_t upper = static_cast<int32_t>(int_value >> kBitsPerInt);
752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (FLAG_trace_osr) {
7531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PrintF("    [sp + %d] <- 0x%08x (upper bits of %g) ; [sp + %d]\n",
754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_offset + kUpperOffset,
755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               upper,
756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               double_value,
757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               *input_offset);
7581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        PrintF("    [sp + %d] <- 0x%08x (lower bits of %g) ; [sp + %d]\n",
759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               output_offset + kLowerOffset,
760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               lower,
761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               double_value,
762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch               *input_offset);
763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output->SetFrameSlot(output_offset + kLowerOffset, lower);
765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      output->SetFrameSlot(output_offset + kUpperOffset, upper);
766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::LITERAL: {
770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Just ignore non-materialized literals.
771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      iterator->Next();
772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      break;
773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case Translation::ARGUMENTS_OBJECT: {
776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Optimized code assumes that the argument object has not been
777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // materialized and so bypasses it when doing arguments access.
778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // We should have bailed out before starting the frame
779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // translation.
780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      UNREACHABLE();
781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return false;
782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (!duplicate) *input_offset -= kPointerSize;
786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return true;
787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Deoptimizer::PatchStackCheckCode(Code* unoptimized_code,
7911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      Code* check_code,
7921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      Code* replacement_code) {
7931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Iterate over the stack check table and patch every stack check
7941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // call to an unconditional call to the replacement code.
7951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(unoptimized_code->kind() == Code::FUNCTION);
7961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Address stack_check_cursor = unoptimized_code->instruction_start() +
7971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unoptimized_code->stack_check_table_offset();
7981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  uint32_t table_length = Memory::uint32_at(stack_check_cursor);
7991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  stack_check_cursor += kIntSize;
8001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (uint32_t i = 0; i < table_length; ++i) {
8011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize);
8021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Address pc_after = unoptimized_code->instruction_start() + pc_offset;
8031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PatchStackCheckCodeAt(pc_after, check_code, replacement_code);
8041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    stack_check_cursor += 2 * kIntSize;
8051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
8061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
8071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Deoptimizer::RevertStackCheckCode(Code* unoptimized_code,
8101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                       Code* check_code,
8111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                       Code* replacement_code) {
8121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Iterate over the stack check table and revert the patched
8131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // stack check calls.
8141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(unoptimized_code->kind() == Code::FUNCTION);
8151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Address stack_check_cursor = unoptimized_code->instruction_start() +
8161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      unoptimized_code->stack_check_table_offset();
8171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  uint32_t table_length = Memory::uint32_at(stack_check_cursor);
8181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  stack_check_cursor += kIntSize;
8191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (uint32_t i = 0; i < table_length; ++i) {
8201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize);
8211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Address pc_after = unoptimized_code->instruction_start() + pc_offset;
8221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    RevertStackCheckCodeAt(pc_after, check_code, replacement_code);
8231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    stack_check_cursor += 2 * kIntSize;
8241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
8251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
8261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned Deoptimizer::ComputeInputFrameSize() const {
829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned fixed_size = ComputeFixedSize(function_);
830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The fp-to-sp delta already takes the context and the function
831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // into account so we have to avoid double counting them (-2).
832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned result = fixed_size + fp_to_sp_delta_ - (2 * kPointerSize);
833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG
834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (bailout_type_ == OSR) {
835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // TODO(kasperl): It would be nice if we could verify that the
836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // size matches with the stack height we can compute based on the
837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // environment at the OSR entry. The code for that his built into
838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // the DoComputeOsrOutputFrame function for now.
839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    unsigned stack_slots = optimized_code_->stack_slots();
841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    unsigned outgoing_size = ComputeOutgoingArgumentSize();
842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    ASSERT(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size);
843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const {
850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The fixed part of the frame consists of the return address, frame
851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // pointer, function, context, and all the incoming arguments.
852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  static const unsigned kFixedSlotSize = 4 * kPointerSize;
853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return ComputeIncomingArgumentSize(function) + kFixedSlotSize;
854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const {
858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The incoming arguments is the values for formal parameters and
859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the receiver. Every slot contains a pointer.
860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned arguments = function->shared()->formal_parameter_count() + 1;
861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return arguments * kPointerSize;
862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned Deoptimizer::ComputeOutgoingArgumentSize() const {
866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizationInputData* data = DeoptimizationInputData::cast(
867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      optimized_code_->deoptimization_data());
868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  unsigned height = data->ArgumentsStackHeight(bailout_id_)->value();
869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return height * kPointerSize;
870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochObject* Deoptimizer::ComputeLiteral(int index) const {
874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizationInputData* data = DeoptimizationInputData::cast(
875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      optimized_code_->deoptimization_data());
876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  FixedArray* literals = data->LiteralArray();
877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return literals->get(index);
878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid Deoptimizer::AddDoubleValue(intptr_t slot_address,
882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                 double value) {
8838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HeapNumberMaterializationDescriptor value_desc(
8848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      reinterpret_cast<Address>(slot_address), value);
8858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  deferred_heap_numbers_.Add(value_desc);
886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochLargeObjectChunk* Deoptimizer::CreateCode(BailoutType type) {
890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // We cannot run this if the serializer is enabled because this will
891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // cause us to emit relocation information for the external
892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // references. This is fine because the deoptimizer's code section
893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // isn't meant to be serialized at all.
894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(!Serializer::enabled());
895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
8968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  MacroAssembler masm(Isolate::Current(), NULL, 16 * KB);
89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  masm.set_emit_debug_code(false);
898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  GenerateDeoptimizationEntries(&masm, kNumberOfEntries, type);
899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CodeDesc desc;
900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  masm.GetCode(&desc);
901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(desc.reloc_size == 0);
902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  LargeObjectChunk* chunk = LargeObjectChunk::New(desc.instr_size, EXECUTABLE);
904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size);
905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size);
906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return chunk;
907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochCode* Deoptimizer::FindDeoptimizingCodeFromAddress(Address addr) {
91144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DeoptimizingCodeListNode* node =
91244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_;
913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (node != NULL) {
914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (node->code()->contains(addr)) return *node->code();
915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    node = node->next();
916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return NULL;
918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::RemoveDeoptimizingCode(Code* code) {
92244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DeoptimizerData* data = Isolate::Current()->deoptimizer_data();
92344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  ASSERT(data->deoptimizing_code_list_ != NULL);
924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Run through the code objects to find this one and remove it.
925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  DeoptimizingCodeListNode* prev = NULL;
92644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  DeoptimizingCodeListNode* current = data->deoptimizing_code_list_;
927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  while (current != NULL) {
928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if (*current->code() == code) {
929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      // Unlink from list. If prev is NULL we are looking at the first element.
930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      if (prev == NULL) {
93144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        data->deoptimizing_code_list_ = current->next();
932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      } else {
933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        prev->set_next(current->next());
934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      }
935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      delete current;
936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return;
937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    }
938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Move to next in list.
939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    prev = current;
940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    current = current->next();
941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Deoptimizing code is removed through weak callback. Each object is expected
943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // to be removed once and only once.
944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();
945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochFrameDescription::FrameDescription(uint32_t frame_size,
949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                   JSFunction* function)
950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    : frame_size_(frame_size),
951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      function_(function),
952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      top_(kZapUint32),
953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      pc_(kZapUint32),
954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      fp_(kZapUint32) {
955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Zap all the registers.
956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int r = 0; r < Register::kNumRegisters; r++) {
957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetRegister(r, kZapUint32);
958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Zap all the slots.
961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (unsigned o = 0; o < frame_size; o += kPointerSize) {
962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    SetFrameSlot(o, kZapUint32);
963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned FrameDescription::GetOffsetFromSlotIndex(Deoptimizer* deoptimizer,
968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                                  int slot_index) {
969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  if (slot_index >= 0) {
970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Local or spill slots. Skip the fixed part of the frame
971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // including all arguments.
972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    unsigned base = static_cast<unsigned>(
973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction()));
974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return base - ((slot_index + 1) * kPointerSize);
975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } else {
976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    // Incoming parameter.
977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    unsigned base = static_cast<unsigned>(GetFrameSize() -
978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch        deoptimizer->ComputeIncomingArgumentSize(GetFunction()));
979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    return base - ((slot_index + 1) * kPointerSize);
980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TranslationBuffer::Add(int32_t value) {
985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Encode the sign bit in the least significant bit.
986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_negative = (value < 0);
987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t bits = ((is_negative ? -value : value) << 1) |
988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      static_cast<int32_t>(is_negative);
989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Encode the individual bytes using the least significant bit of
990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // each byte to indicate whether or not more bytes follow.
991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  do {
992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    uint32_t next = bits >> 7;
993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    contents_.Add(((bits << 1) & 0xFF) | (next != 0));
994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bits = next;
995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  } while (bits != 0);
996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint32_t TranslationIterator::Next() {
1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  ASSERT(HasNext());
1001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Run through the bytes until we reach one with a least significant
1002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // bit of zero (marks the end).
1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  uint32_t bits = 0;
1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; true; i += 7) {
1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    uint8_t next = buffer_->get(index_++);
1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    bits |= (next >> 1) << i;
1007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    if ((next & 1) == 0) break;
1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // The bits encode the sign in the least significant bit.
1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  bool is_negative = (bits & 1) == 1;
1011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int32_t result = bits >> 1;
1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return is_negative ? -result : result;
1013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHandle<ByteArray> TranslationBuffer::CreateByteArray() {
1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int length = contents_.length();
101844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Handle<ByteArray> result =
101944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::Current()->factory()->NewByteArray(length, TENURED);
1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  memcpy(result->GetDataStartAddress(), contents_.ToVector().start(), length);
1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return result;
1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::BeginFrame(int node_id, int literal_id, unsigned height) {
1026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(FRAME);
1027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(node_id);
1028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(literal_id);
1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(height);
1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreRegister(Register reg) {
1034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(REGISTER);
1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(reg.code());
1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreInt32Register(Register reg) {
1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(INT32_REGISTER);
1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(reg.code());
1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreDoubleRegister(DoubleRegister reg) {
1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(DOUBLE_REGISTER);
1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(DoubleRegister::ToAllocationIndex(reg));
1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreStackSlot(int index) {
1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(STACK_SLOT);
1053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(index);
1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreInt32StackSlot(int index) {
1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(INT32_STACK_SLOT);
1059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(index);
1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreDoubleStackSlot(int index) {
1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(DOUBLE_STACK_SLOT);
1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(index);
1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreLiteral(int literal_id) {
1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(LITERAL);
1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(literal_id);
1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreArgumentsObject() {
1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(ARGUMENTS_OBJECT);
1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::MarkDuplicate() {
1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  buffer_->Add(DUPLICATE);
1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint Translation::NumberOfOperandsFor(Opcode opcode) {
1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (opcode) {
1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case ARGUMENTS_OBJECT:
1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case DUPLICATE:
1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return 0;
1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case BEGIN:
1091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case REGISTER:
1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case INT32_REGISTER:
1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case DOUBLE_REGISTER:
1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case STACK_SLOT:
1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case INT32_STACK_SLOT:
1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case DOUBLE_STACK_SLOT:
1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case LITERAL:
1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return 1;
1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case FRAME:
1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return 3;
1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();
1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return -1;
1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef OBJECT_PRINT
1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* Translation::StringFor(Opcode opcode) {
1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  switch (opcode) {
1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case BEGIN:
1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "BEGIN";
1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case FRAME:
1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "FRAME";
1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case REGISTER:
1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "REGISTER";
1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case INT32_REGISTER:
1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "INT32_REGISTER";
1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case DOUBLE_REGISTER:
1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "DOUBLE_REGISTER";
1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case STACK_SLOT:
1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "STACK_SLOT";
1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case INT32_STACK_SLOT:
1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "INT32_STACK_SLOT";
1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case DOUBLE_STACK_SLOT:
1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "DOUBLE_STACK_SLOT";
1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case LITERAL:
1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "LITERAL";
1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case ARGUMENTS_OBJECT:
1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "ARGUMENTS_OBJECT";
1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    case DUPLICATE:
1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch      return "DUPLICATE";
1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  UNREACHABLE();
1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  return "";
1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif
1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochDeoptimizingCodeListNode::DeoptimizingCodeListNode(Code* code): next_(NULL) {
114244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GlobalHandles* global_handles = Isolate::Current()->global_handles();
1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Globalize the code object and make it weak.
114444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  code_ = Handle<Code>::cast(global_handles->Create(code));
114544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->MakeWeak(reinterpret_cast<Object**>(code_.location()),
114644f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           this,
114744f0eee88ff00398ff7f715fab053374d808c90dSteve Block                           Deoptimizer::HandleWeakDeoptimizedCode);
1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochDeoptimizingCodeListNode::~DeoptimizingCodeListNode() {
115244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  GlobalHandles* global_handles = Isolate::Current()->global_handles();
115344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  global_handles->Destroy(reinterpret_cast<Object**>(code_.location()));
1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
11578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// We can't intermix stack decoding and allocations because
11588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// deoptimization infrastracture is not GC safe.
11598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Thus we build a temporary structure in malloced space.
11608b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochSlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator,
11618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                            DeoptimizationInputData* data,
11628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                            JavaScriptFrame* frame) {
11638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Translation::Opcode opcode =
11648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      static_cast<Translation::Opcode>(iterator->Next());
11658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  switch (opcode) {
11678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::BEGIN:
11688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::FRAME:
11698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // Peeled off before getting here.
11708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      break;
11718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::ARGUMENTS_OBJECT:
11738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // This can be only emitted for local slots not for argument slots.
11748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      break;
11758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::REGISTER:
11778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::INT32_REGISTER:
11788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::DOUBLE_REGISTER:
11798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::DUPLICATE:
11808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // We are at safepoint which corresponds to call.  All registers are
11818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // saved by caller so there would be no live registers at this
11828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      // point. Thus these translation commands should not be used.
11838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      break;
11848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::STACK_SLOT: {
11868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      int slot_index = iterator->Next();
11878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      Address slot_addr = SlotAddress(frame, slot_index);
11888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return SlotRef(slot_addr, SlotRef::TAGGED);
11898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
11908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::INT32_STACK_SLOT: {
11928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      int slot_index = iterator->Next();
11938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      Address slot_addr = SlotAddress(frame, slot_index);
11948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return SlotRef(slot_addr, SlotRef::INT32);
11958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
11968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
11978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::DOUBLE_STACK_SLOT: {
11988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      int slot_index = iterator->Next();
11998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      Address slot_addr = SlotAddress(frame, slot_index);
12008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return SlotRef(slot_addr, SlotRef::DOUBLE);
12018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
12028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    case Translation::LITERAL: {
12048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      int literal_index = iterator->Next();
12058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      return SlotRef(data->LiteralArray()->get(literal_index));
12068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
12078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
12088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  UNREACHABLE();
12108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  return SlotRef();
12118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
12128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid SlotRef::ComputeSlotMappingForArguments(JavaScriptFrame* frame,
12158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                             int inlined_frame_index,
12168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                                             Vector<SlotRef>* args_slots) {
12178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  AssertNoAllocation no_gc;
12188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int deopt_index = AstNode::kNoNumber;
12198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  DeoptimizationInputData* data =
12208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index);
12218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  TranslationIterator it(data->TranslationByteArray(),
12228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch                         data->TranslationIndex(deopt_index)->value());
12238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
12248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(opcode == Translation::BEGIN);
12258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int frame_count = it.Next();
12268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  USE(frame_count);
12278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  ASSERT(frame_count > inlined_frame_index);
12288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  int frames_to_skip = inlined_frame_index;
12298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  while (true) {
12308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    opcode = static_cast<Translation::Opcode>(it.Next());
12318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    // Skip over operands to advance to the next opcode.
12328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    it.Skip(Translation::NumberOfOperandsFor(opcode));
12338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    if (opcode == Translation::FRAME) {
12348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (frames_to_skip == 0) {
12358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // We reached the frame corresponding to the inlined function
12368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // in question.  Process the translation commands for the
12378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // arguments.
12388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        //
12398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // Skip the translation command for the receiver.
12408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        it.Skip(Translation::NumberOfOperandsFor(
12418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch            static_cast<Translation::Opcode>(it.Next())));
12428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        // Compute slots for arguments.
12438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        for (int i = 0; i < args_slots->length(); ++i) {
12448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame);
12458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        }
12468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch        return;
12478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      }
12488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      frames_to_skip--;
12498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    }
12508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  }
12518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  UNREACHABLE();
12538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch}
12548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
12558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch
1256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} }  // namespace v8::internal
1257