13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
281362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// Redistribution and use in source and binary forms, with or without
381362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// modification, are permitted provided that the following conditions are
481362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// met:
581362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//
681362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//     * Redistributions of source code must retain the above copyright
781362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//       notice, this list of conditions and the following disclaimer.
881362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//     * Redistributions in binary form must reproduce the above
981362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//       copyright notice, this list of conditions and the following
1081362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//       disclaimer in the documentation and/or other materials provided
1181362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//       with the distribution.
1281362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//     * Neither the name of Google Inc. nor the names of its
1381362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//       contributors may be used to endorse or promote products derived
1481362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//       from this software without specific prior written permission.
1581362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen//
1681362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1781362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1881362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1981362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2081362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2181362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2281362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2381362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2481362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2581362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2681362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2781362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen
28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "v8.h"
2981362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen
30b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#if defined(V8_TARGET_ARCH_X64)
31b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "codegen.h"
33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h"
34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h"
35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "safepoint-table.h"
3681362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen
37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 {
38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal {
3981362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen
40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
4169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochconst int Deoptimizer::table_entry_size_ = 10;
42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Deoptimizer::patch_size() {
452b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  return Assembler::kCallInstructionLength;
4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block
4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DeoptimizeFunction(JSFunction* function) {
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HandleScope scope;
511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  AssertNoAllocation no_allocation;
521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (!function->IsOptimized()) return;
541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Get the optimized code.
561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Code* code = function->code();
571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Invalidate the relocation information, as it will become invalid by the
591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // code patching below, and is not needed any more.
601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  code->InvalidateRelocation();
611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
622b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  // For each LLazyBailout instruction insert a absolute call to the
631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // corresponding deoptimization entry, or a short call to an absolute
641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // jump if space is short. The absolute jumps are put in a table just
651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // before the safepoint table (space was allocated there when the Code
661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // object was created, if necessary).
671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Address instruction_start = function->code()->instruction_start();
691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG
702b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  Address prev_call_address = NULL;
711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
722b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  DeoptimizationInputData* deopt_data =
732b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch      DeoptimizationInputData::cast(code->deoptimization_data());
742b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
752b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    if (deopt_data->Pc(i)->value() == -1) continue;
761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Position where Call will be patched in.
772b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    Address call_address = instruction_start + deopt_data->Pc(i)->value();
782b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    // There is room enough to write a long call instruction because we pad
792b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    // LLazyBailout instructions with nops if necessary.
802b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    CodePatcher patcher(call_address, Assembler::kCallInstructionLength);
812b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    patcher.masm()->Call(GetDeoptimizationEntry(i, LAZY), RelocInfo::NONE);
822b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    ASSERT(prev_call_address == NULL ||
832b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch           call_address >= prev_call_address + patch_size());
842b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    ASSERT(call_address + patch_size() <= code->instruction_end());
853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef DEBUG
862b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    prev_call_address = call_address;
873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif
881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Isolate* isolate = code->GetIsolate();
911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Add the deoptimizing code to the list.
931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code);
943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  DeoptimizerData* data = isolate->deoptimizer_data();
9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  node->set_next(data->deoptimizing_code_list_);
9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  data->deoptimizing_code_list_ = node;
971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // We might be in the middle of incremental marking with compaction.
993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Tell collector to treat this code object in a special way and
1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // ignore all slots that might have been recorded on it.
1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  isolate->heap()->mark_compact_collector()->InvalidateCode(code);
1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Set the code for the function to non-optimized version.
1041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  function->ReplaceCode(function->shared()->code());
1051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (FLAG_trace_deopt) {
1071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PrintF("[forced deoptimization: ");
1081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    function->PrintName();
1091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function));
1101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code,
1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                        Address pc_after,
1161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        Code* check_code,
1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                        Code* replacement_code) {
118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Address call_target_address = pc_after - kIntSize;
119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(check_code->entry() ==
120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         Assembler::target_address_at(call_target_address));
121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // The stack check code matches the pattern:
122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //
123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     cmp rsp, <limit>
124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     jae ok
125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     call <stack guard>
126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     test rax, <loop nesting depth>
127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // ok: ...
128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //
129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // We will patch away the branch so the code is:
130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //
131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     cmp rsp, <limit>  ;; Not changed
132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     nop
133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     nop
134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     call <on-stack replacment>
135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //     test rax, <loop nesting depth>
136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // ok:
137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  //
138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(*(call_target_address - 3) == 0x73 &&  // jae
139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         *(call_target_address - 2) == 0x07 &&  // offset
140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         *(call_target_address - 1) == 0xe8);   // call
1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *(call_target_address - 3) = 0x66;  // 2 byte nop part 1
1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  *(call_target_address - 2) = 0x90;  // 2 byte nop part 2
143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Assembler::set_target_address_at(call_target_address,
144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   replacement_code->entry());
1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      unoptimized_code, call_target_address, replacement_code);
148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::RevertStackCheckCodeAt(Code* unoptimized_code,
1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                         Address pc_after,
1531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                         Code* check_code,
1541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                         Code* replacement_code) {
155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Address call_target_address = pc_after - kIntSize;
156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(replacement_code->entry() ==
157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         Assembler::target_address_at(call_target_address));
158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to
159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // restore the conditional branch.
1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(*(call_target_address - 3) == 0x66 &&  // 2 byte nop part 1
1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch         *(call_target_address - 2) == 0x90 &&  // 2 byte nop part 2
162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch         *(call_target_address - 1) == 0xe8);   // call
163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  *(call_target_address - 3) = 0x73;  // jae
164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  *(call_target_address - 2) = 0x07;  // offset
165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Assembler::set_target_address_at(call_target_address,
166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch                                   check_code->entry());
1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  check_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      unoptimized_code, call_target_address, check_code);
170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch}
171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic int LookupBailoutId(DeoptimizationInputData* data, unsigned ast_id) {
174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ByteArray* translations = data->TranslationByteArray();
175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int length = data->DeoptCount();
176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < length; i++) {
177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (static_cast<unsigned>(data->AstId(i)->value()) == ast_id) {
178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      TranslationIterator it(translations,  data->TranslationIndex(i)->value());
179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      int value = it.Next();
180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      ASSERT(Translation::BEGIN == static_cast<Translation::Opcode>(value));
181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      // Read the number of frames.
182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      value = it.Next();
183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      if (value == 1) return i;
184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  UNREACHABLE();
187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  return -1;
188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DoComputeOsrOutputFrame() {
192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  DeoptimizationInputData* data = DeoptimizationInputData::cast(
193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      optimized_code_->deoptimization_data());
194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned ast_id = data->OsrAstId()->value();
195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // TODO(kasperl): This should not be the bailout_id_. It should be
196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // the ast id. Confusing.
197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(bailout_id_ == ast_id);
198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int bailout_id = LookupBailoutId(data, ast_id);
200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned translation_index = data->TranslationIndex(bailout_id)->value();
201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ByteArray* translations = data->TranslationByteArray();
202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  TranslationIterator iterator(translations, translation_index);
204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  Translation::Opcode opcode =
205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      static_cast<Translation::Opcode>(iterator.Next());
206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(Translation::BEGIN == opcode);
207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  USE(opcode);
208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int count = iterator.Next();
2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  iterator.Skip(1);  // Drop JS frame count.
210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(count == 1);
211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  USE(count);
212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  opcode = static_cast<Translation::Opcode>(iterator.Next());
214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  USE(opcode);
2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(Translation::JS_FRAME == opcode);
216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned node_id = iterator.Next();
217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  USE(node_id);
218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(node_id == ast_id);
219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator.Next()));
220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  USE(function);
221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(function == function_);
222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned height = iterator.Next();
223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned height_in_bytes = height * kPointerSize;
224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  USE(height_in_bytes);
225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned fixed_size = ComputeFixedSize(function_);
2273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  unsigned input_frame_size = input_->GetFrameSize();
228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(fixed_size + height_in_bytes == input_frame_size);
229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize;
231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value();
232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned outgoing_size = outgoing_height * kPointerSize;
233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size;
234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  ASSERT(outgoing_size == 0);  // OSR does not happen in the middle of a call.
235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_trace_osr) {
237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ",
238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           reinterpret_cast<intptr_t>(function_));
239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    function_->PrintName();
240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF(" => node=%u, frame=%d->%d]\n",
241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           ast_id,
242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           input_frame_size,
243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           output_frame_size);
244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // There's only one output frame in the OSR case.
247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  output_count_ = 1;
248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  output_ = new FrameDescription*[1];
249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  output_[0] = new(output_frame_size) FrameDescription(
250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      output_frame_size, function_);
2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT);
252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Clear the incoming parameters in the optimized frame to avoid
254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // confusing the garbage collector.
255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  unsigned output_offset = output_frame_size - kPointerSize;
256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int parameter_count = function_->shared()->formal_parameter_count() + 1;
257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  for (int i = 0; i < parameter_count; ++i) {
258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    output_[0]->SetFrameSlot(output_offset, 0);
259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    output_offset -= kPointerSize;
260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Translate the incoming parameters. This may overwrite some of the
263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // incoming argument slots we've just cleared.
264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int input_offset = input_frame_size - kPointerSize;
265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  bool ok = true;
266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  int limit = input_offset - (parameter_count * kPointerSize);
267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (ok && input_offset > limit) {
268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ok = DoOsrTranslateCommand(&iterator, &input_offset);
269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // There are no translation commands for the caller's pc and fp, the
272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // context, and the function.  Set them up explicitly.
27344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  for (int i = StandardFrameConstants::kCallerPCOffset;
27444f0eee88ff00398ff7f715fab053374d808c90dSteve Block       ok && i >=  StandardFrameConstants::kMarkerOffset;
27544f0eee88ff00398ff7f715fab053374d808c90dSteve Block       i -= kPointerSize) {
276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    intptr_t input_value = input_->GetFrameSlot(input_offset);
277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    if (FLAG_trace_osr) {
27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block      const char* name = "UNKNOWN";
27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      switch (i) {
28044f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case StandardFrameConstants::kCallerPCOffset:
28144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          name = "caller's pc";
28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
28344f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case StandardFrameConstants::kCallerFPOffset:
28444f0eee88ff00398ff7f715fab053374d808c90dSteve Block          name = "fp";
28544f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
28644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case StandardFrameConstants::kContextOffset:
28744f0eee88ff00398ff7f715fab053374d808c90dSteve Block          name = "context";
28844f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        case StandardFrameConstants::kMarkerOffset:
29044f0eee88ff00398ff7f715fab053374d808c90dSteve Block          name = "function";
29144f0eee88ff00398ff7f715fab053374d808c90dSteve Block          break;
29244f0eee88ff00398ff7f715fab053374d808c90dSteve Block      }
29344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      PrintF("    [rsp + %d] <- 0x%08" V8PRIxPTR " ; [rsp + %d] "
29444f0eee88ff00398ff7f715fab053374d808c90dSteve Block             "(fixed part - %s)\n",
295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             output_offset,
296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch             input_value,
29744f0eee88ff00398ff7f715fab053374d808c90dSteve Block             input_offset,
29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block             name);
299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    }
300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset));
301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    input_offset -= kPointerSize;
302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    output_offset -= kPointerSize;
303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // Translate the rest of the frame.
306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  while (ok && input_offset >= 0) {
307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    ok = DoOsrTranslateCommand(&iterator, &input_offset);
308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // If translation of any command failed, continue using the input frame.
311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (!ok) {
312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    delete output_[0];
313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    output_[0] = input_;
314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    output_[0]->SetPc(reinterpret_cast<intptr_t>(from_));
315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    // Set up the frame pointer and the context pointer.
317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    output_[0]->SetRegister(rbp.code(), input_->GetRegister(rbp.code()));
318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    output_[0]->SetRegister(rsi.code(), input_->GetRegister(rsi.code()));
319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    unsigned pc_offset = data->OsrPcOffset()->value();
321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    intptr_t pc = reinterpret_cast<intptr_t>(
322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch        optimized_code_->entry() + pc_offset);
323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    output_[0]->SetPc(pc);
324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Code* continuation =
32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block      function->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR);
327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  output_[0]->SetContinuation(
328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch      reinterpret_cast<intptr_t>(continuation->entry()));
329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch
330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (FLAG_trace_osr) {
331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ",
332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           ok ? "finished" : "aborted",
333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch           reinterpret_cast<intptr_t>(function));
334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    function->PrintName();
335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    PrintF(" => pc=0x%0" V8PRIxPTR "]\n", output_[0]->GetPc());
336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator,
3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                                 int frame_index) {
3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned height = iterator->Next();
3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned height_in_bytes = height * kPointerSize;
3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("  translating arguments adaptor => height=%d\n", height_in_bytes);
3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize;
3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate and store the output frame description.
3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameDescription* output_frame =
3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(output_frame_size) FrameDescription(output_frame_size, function);
3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR);
3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Arguments adaptor can not be topmost or bottommost.
3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(output_[frame_index] == NULL);
3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_[frame_index] = output_frame;
3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The top address of the frame is computed from the previous
3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // frame's top and this frame's size.
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t top_address;
3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetTop(top_address);
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compute the incoming parameter translation.
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int parameter_count = height;
3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned output_offset = output_frame_size;
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < parameter_count; ++i) {
3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    output_offset -= kPointerSize;
3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoTranslateCommand(iterator, frame_index, output_offset);
3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Read caller's PC from the previous frame.
3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, callers_pc);
3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; caller's pc\n",
3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           top_address + output_offset, output_offset, callers_pc);
3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Read caller's FP from the previous frame, and set this frame's FP.
3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t value = output_[frame_index - 1]->GetFp();
3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, value);
3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t fp_value = top_address + output_offset;
3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFp(fp_value);
3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; caller's fp\n",
3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fp_value, output_offset, value);
3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // A marker value is used in place of the context.
3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t context = reinterpret_cast<intptr_t>(
4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR));
4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, context);
4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; context (adaptor sentinel)\n",
4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           top_address + output_offset, output_offset, context);
4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME.
4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  value = reinterpret_cast<intptr_t>(function);
4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, value);
4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; function\n",
4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           top_address + output_offset, output_offset, value);
4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Number of incoming arguments.
4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, value);
4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; argc (%d)\n",
4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           top_address + output_offset, output_offset, value, height - 1);
4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(0 == output_offset);
4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Builtins* builtins = isolate_->builtins();
4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  Code* adaptor_trampoline =
4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      builtins->builtin(Builtins::kArgumentsAdaptorTrampoline);
4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t pc_value = reinterpret_cast<intptr_t>(
4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      adaptor_trampoline->instruction_start() +
4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value());
4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetPc(pc_value);
4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator,
4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                              int frame_index) {
4439413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch  Builtins* builtins = isolate_->builtins();
4449413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch  Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric);
4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned height = iterator->Next();
4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned height_in_bytes = height * kPointerSize;
4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("  translating construct stub => height=%d\n", height_in_bytes);
4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4529413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch  unsigned fixed_frame_size = 7 * kPointerSize;
4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Allocate and store the output frame description.
4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  FrameDescription* output_frame =
4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      new(output_frame_size) FrameDescription(output_frame_size, function);
4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameType(StackFrame::CONSTRUCT);
4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Construct stub can not be topmost or bottommost.
4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(frame_index > 0 && frame_index < output_count_ - 1);
4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(output_[frame_index] == NULL);
4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_[frame_index] = output_frame;
4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The top address of the frame is computed from the previous
4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // frame's top and this frame's size.
4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t top_address;
4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetTop(top_address);
4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Compute the incoming parameter translation.
4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  int parameter_count = height;
4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  unsigned output_offset = output_frame_size;
4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  for (int i = 0; i < parameter_count; ++i) {
4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    output_offset -= kPointerSize;
4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    DoTranslateCommand(iterator, frame_index, output_offset);
4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Read caller's PC from the previous frame.
4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t callers_pc = output_[frame_index - 1]->GetPc();
4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, callers_pc);
4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; caller's pc\n",
4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           top_address + output_offset, output_offset, callers_pc);
4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Read caller's FP from the previous frame, and set this frame's FP.
4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t value = output_[frame_index - 1]->GetFp();
4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, value);
4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t fp_value = top_address + output_offset;
4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFp(fp_value);
4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; caller's fp\n",
4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           fp_value, output_offset, value);
4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The context can be gotten from the previous frame.
5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  value = output_[frame_index - 1]->GetContext();
5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, value);
5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; context\n",
5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           top_address + output_offset, output_offset, value);
5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // A marker value is used in place of the function.
5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT));
5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, value);
5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; function (construct sentinel)\n",
5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           top_address + output_offset, output_offset, value);
5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5219413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch  // The output frame reflects a JSConstructStubGeneric frame.
5229413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch  output_offset -= kPointerSize;
5239413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch  value = reinterpret_cast<intptr_t>(construct_stub);
5249413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch  output_frame->SetFrameSlot(output_offset, value);
5259413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch  if (FLAG_trace_deopt) {
5269413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
5279413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch           V8PRIxPTR " ; code object\n",
5289413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch           top_address + output_offset, output_offset, value);
5299413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch  }
5309413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch
5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // Number of incoming arguments.
5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1));
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, value);
5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; argc (%d)\n",
5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           top_address + output_offset, output_offset, value, height - 1);
5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // The newly allocated object was passed as receiver in the artificial
5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  // constructor stub environment created by HEnvironment::CopyForInlining().
5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_offset -= kPointerSize;
5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  value = output_frame->GetFrameSlot(output_frame_size - kPointerSize);
5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameSlot(output_offset, value);
5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  if (FLAG_trace_deopt) {
5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           V8PRIxPTR " ; allocated receiver\n",
5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch           top_address + output_offset, output_offset, value);
5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  ASSERT(0 == output_offset);
5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  intptr_t pc = reinterpret_cast<intptr_t>(
5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      construct_stub->instruction_start() +
5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch      isolate_->heap()->construct_stub_deopt_pc_offset()->value());
5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetPc(pc);
5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch}
5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch
5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator,
5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                                   int frame_index) {
5631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int node_id = iterator->Next();
5641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next()));
5651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  unsigned height = iterator->Next();
5661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  unsigned height_in_bytes = height * kPointerSize;
5671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (FLAG_trace_deopt) {
5681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PrintF("  translating ");
5691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    function->PrintName();
5701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PrintF(" => node=%d, height=%d\n", node_id, height_in_bytes);
5711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
5721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The 'fixed' part of the frame consists of the incoming parameters and
5741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the part described by JavaScriptFrameConstants.
5751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  unsigned fixed_frame_size = ComputeFixedSize(function);
5763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  unsigned input_frame_size = input_->GetFrameSize();
5771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  unsigned output_frame_size = height_in_bytes + fixed_frame_size;
5781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Allocate and store the output frame description.
5801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  FrameDescription* output_frame =
5811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      new(output_frame_size) FrameDescription(output_frame_size, function);
5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetFrameType(StackFrame::JAVA_SCRIPT);
5831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool is_bottommost = (0 == frame_index);
5851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  bool is_topmost = (output_count_ - 1 == frame_index);
5861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(frame_index >= 0 && frame_index < output_count_);
5871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(output_[frame_index] == NULL);
5881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_[frame_index] = output_frame;
5891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
5901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The top address for the bottommost output frame can be computed from
5911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the input frame pointer and the output frame's height.  For all
5921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // subsequent output frames, it can be computed from the previous one's
5931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // top address and the current frame's size.
5941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  intptr_t top_address;
5951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_bottommost) {
5961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // 2 = context and function in the frame.
5971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    top_address =
5981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        input_->GetRegister(rbp.code()) - (2 * kPointerSize) - height_in_bytes;
5991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
6001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    top_address = output_[frame_index - 1]->GetTop() - output_frame_size;
6011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_frame->SetTop(top_address);
6031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Compute the incoming parameter translation.
6051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int parameter_count = function->shared()->formal_parameter_count() + 1;
6061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  unsigned output_offset = output_frame_size;
6071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  unsigned input_offset = input_frame_size;
6081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < parameter_count; ++i) {
6091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    output_offset -= kPointerSize;
6101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DoTranslateCommand(iterator, frame_index, output_offset);
6111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  input_offset -= (parameter_count * kPointerSize);
6131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // There are no translation commands for the caller's pc and fp, the
6151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // context, and the function.  Synthesize their values and set them up
6161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // explicitly.
6171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  //
6181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The caller's pc for the bottommost output frame is the same as in the
6191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // input frame.  For all subsequent output frames, it can be read from the
6201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // previous one.  This frame's pc can be computed from the non-optimized
6211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // function code and AST id of the bailout.
6221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_offset -= kPointerSize;
6231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  input_offset -= kPointerSize;
6241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  intptr_t value;
6251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_bottommost) {
6261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value = input_->GetFrameSlot(input_offset);
6271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
6281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value = output_[frame_index - 1]->GetPc();
6291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_frame->SetFrameSlot(output_offset, value);
6311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (FLAG_trace_deopt) {
6321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
6331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           V8PRIxPTR  " ; caller's pc\n",
6341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           top_address + output_offset, output_offset, value);
6351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The caller's frame pointer for the bottommost output frame is the same
6381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // as in the input frame.  For all subsequent output frames, it can be
6391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // read from the previous one.  Also compute and set this frame's frame
6401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // pointer.
6411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_offset -= kPointerSize;
6421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  input_offset -= kPointerSize;
6431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_bottommost) {
6441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value = input_->GetFrameSlot(input_offset);
6451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
6461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    value = output_[frame_index - 1]->GetFp();
6471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_frame->SetFrameSlot(output_offset, value);
6491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  intptr_t fp_value = top_address + output_offset;
6501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(!is_bottommost || input_->GetRegister(rbp.code()) == fp_value);
6511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_frame->SetFp(fp_value);
6521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_topmost) output_frame->SetRegister(rbp.code(), fp_value);
6531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (FLAG_trace_deopt) {
6541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
6551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           V8PRIxPTR " ; caller's fp\n",
6561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           fp_value, output_offset, value);
6571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
659e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // For the bottommost output frame the context can be gotten from the input
660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // frame. For all subsequent output frames it can be gotten from the function
661e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  // so long as we don't inline functions that need local contexts.
6621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_offset -= kPointerSize;
6631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  input_offset -= kPointerSize;
664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  if (is_bottommost) {
665e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    value = input_->GetFrameSlot(input_offset);
666e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  } else {
667e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch    value = reinterpret_cast<intptr_t>(function->context());
668e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  }
6691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_frame->SetFrameSlot(output_offset, value);
6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  output_frame->SetContext(value);
6711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (is_topmost) output_frame->SetRegister(rsi.code(), value);
6721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (FLAG_trace_deopt) {
6731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
6741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           V8PRIxPTR "; context\n",
6751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           top_address + output_offset, output_offset, value);
6761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The function was mentioned explicitly in the BEGIN_FRAME.
6791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_offset -= kPointerSize;
6801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  input_offset -= kPointerSize;
6811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  value = reinterpret_cast<intptr_t>(function);
6821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // The function for the bottommost output frame should also agree with the
6831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // input frame.
6841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
6851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_frame->SetFrameSlot(output_offset, value);
6861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (FLAG_trace_deopt) {
6871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    PrintF("    0x%08" V8PRIxPTR ": [top + %d] <- 0x%08"
6881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           V8PRIxPTR "; function\n",
6891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block           top_address + output_offset, output_offset, value);
6901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Translate the rest of the frame.
6931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (unsigned i = 0; i < height; ++i) {
6941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    output_offset -= kPointerSize;
6951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    DoTranslateCommand(iterator, frame_index, output_offset);
6961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
6971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ASSERT(0 == output_offset);
6981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
6991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Compute this frame's PC, state, and continuation.
7001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Code* non_optimized_code = function->shared()->code();
7011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  FixedArray* raw_data = non_optimized_code->deoptimization_data();
7021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data);
7031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Address start = non_optimized_code->instruction_start();
7041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared());
7051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state);
7061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset);
7071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_frame->SetPc(pc_value);
7081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  FullCodeGenerator::State state =
7101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      FullCodeGenerator::StateField::decode(pc_and_state);
7111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  output_frame->SetState(Smi::FromInt(state));
7121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Set the continuation for the topmost frame.
7143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  if (is_topmost && bailout_type_ != DEBUGGER) {
7151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    Code* continuation = (bailout_type_ == EAGER)
71644f0eee88ff00398ff7f715fab053374d808c90dSteve Block        ? isolate_->builtins()->builtin(Builtins::kNotifyDeoptimized)
71744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        : isolate_->builtins()->builtin(Builtins::kNotifyLazyDeoptimized);
7181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    output_frame->SetContinuation(
7191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block        reinterpret_cast<intptr_t>(continuation->entry()));
7201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
7243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
7253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Set the register values. The values are not important as there are no
7263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // callee saved registers in JavaScript frames, so all registers are
7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // spilled. Registers rbp and rsp are set to the correct values though.
7283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < Register::kNumRegisters; i++) {
7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    input_->SetRegister(i, i * 4);
7303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
7313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  input_->SetRegister(rsp.code(), reinterpret_cast<intptr_t>(frame->sp()));
7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  input_->SetRegister(rbp.code(), reinterpret_cast<intptr_t>(frame->fp()));
7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) {
7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    input_->SetDoubleRegister(i, 0.0);
7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
7363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Fill the frame content from the actual data on the frame.
7383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) {
7393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    input_->SetFrameSlot(i, Memory::uint64_at(tos + i));
7403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
7413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
7423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
7441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#define __ masm()->
7451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::EntryGenerator::Generate() {
7471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  GeneratePrologue();
7481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Save all general purpose registers before messing with them.
7501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int kNumberOfRegisters = Register::kNumRegisters;
7511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int kDoubleRegsSize = kDoubleSize *
7531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                              XMMRegister::kNumAllocatableRegisters;
7541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ subq(rsp, Immediate(kDoubleRegsSize));
7551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
7571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
7581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = i * kDoubleSize;
7591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movsd(Operand(rsp, offset), xmm_reg);
7601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
7611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We push all registers onto the stack, even though we do not need
7631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // to restore all later.
7641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < kNumberOfRegisters; i++) {
7653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Register r = Register::from_code(i);
7661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ push(r);
7671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
7681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize +
7701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block                                      kDoubleRegsSize;
7711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // When calling new_deoptimizer_function we need to pass the last argument
7731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // on the stack on windows and in r8 on linux. The remaining arguments are
7741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // all passed in registers (different ones on linux and windows though).
7751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef _WIN64
7771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register arg4 = r9;
7781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register arg3 = r8;
7791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register arg2 = rdx;
7801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register arg1 = rcx;
7811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#else
7821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register arg4 = rcx;
7831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register arg3 = rdx;
7841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register arg2 = rsi;
7851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register arg1 = rdi;
7861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
7871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We use this to keep the value of the fifth argument temporarily.
7891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unfortunately we can't store it directly in r8 (used for passing
7901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // this on linux), since it is another parameter passing register on windows.
7911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Register arg5 = r11;
7921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Get the bailout id from the stack.
7941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(arg3, Operand(rsp, kSavedRegistersAreaSize));
7951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
7961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Get the address of the location in the code object if possible
7971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // and compute the fp-to-sp delta in register arg5.
7981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (type() == EAGER) {
7991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ Set(arg4, 0);
8001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ lea(arg5, Operand(rsp, kSavedRegistersAreaSize + 1 * kPointerSize));
8011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
8021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ movq(arg4, Operand(rsp, kSavedRegistersAreaSize + 1 * kPointerSize));
8031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ lea(arg5, Operand(rsp, kSavedRegistersAreaSize + 2 * kPointerSize));
8041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
8051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ subq(arg5, rbp);
8071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ neg(arg5);
8081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Allocate a new deoptimizer object.
8108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ PrepareCallCFunction(6);
8111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset));
8121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(arg1, rax);
8138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ Set(arg2, type());
8141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Args 3 and 4 are already in the right registers.
8151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // On windows put the arguments on the stack (PrepareCallCFunction
8178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  // has created space for this). On linux pass the arguments in r8 and r9.
8181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef _WIN64
819e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ movq(Operand(rsp, 4 * kPointerSize), arg5);
8208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ LoadAddress(arg5, ExternalReference::isolate_address());
8218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ movq(Operand(rsp, 5 * kPointerSize), arg5);
8221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#else
8231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(r8, arg5);
8248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ LoadAddress(r9, ExternalReference::isolate_address());
8251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif
8261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
82744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = masm()->isolate();
82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AllowExternalCallThatCantCauseGC scope(masm());
8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6);
8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Preserve deoptimizer object in register rax and get the input
8341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // frame descriptor pointer.
8351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rbx, Operand(rax, Deoptimizer::input_offset()));
8361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Fill in the input registers.
8381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = kNumberOfRegisters -1; i >= 0; i--) {
8391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = (i * kPointerSize) + FrameDescription::registers_offset();
8401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ pop(Operand(rbx, offset));
8411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
8421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Fill in the double input registers.
8441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  int double_regs_offset = FrameDescription::double_registers_offset();
8451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) {
8461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int dst_offset = i * kDoubleSize + double_regs_offset;
8471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ pop(Operand(rbx, dst_offset));
8481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
8491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Remove the bailout id from the stack.
8511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (type() == EAGER) {
8521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ addq(rsp, Immediate(kPointerSize));
8531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  } else {
8541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ addq(rsp, Immediate(2 * kPointerSize));
8551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
8561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Compute a pointer to the unwinding limit in register rcx; that is
8581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // the first stack slot not part of the input frame.
8591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rcx, Operand(rbx, FrameDescription::frame_size_offset()));
8601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ addq(rcx, rsp);
8611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Unwind the stack down to - but not including - the unwinding
8631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // limit and copy the contents of the activation frame to the input
8641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // frame description.
8651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ lea(rdx, Operand(rbx, FrameDescription::frame_content_offset()));
8661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label pop_loop;
8671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&pop_loop);
8681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ pop(Operand(rdx, 0));
8691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ addq(rdx, Immediate(sizeof(intptr_t)));
8701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ cmpq(rcx, rsp);
8711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(not_equal, &pop_loop);
8721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Compute the output frame in the deoptimizer.
8741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ push(rax);
8758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ PrepareCallCFunction(2);
8761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(arg1, rax);
8778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ LoadAddress(arg2, ExternalReference::isolate_address());
8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AllowExternalCallThatCantCauseGC scope(masm());
8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallCFunction(
8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch        ExternalReference::compute_output_frames_function(isolate), 2);
8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
8831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ pop(rax);
8841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
8851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Replace the current frame with the output frames.
8861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label outer_push_loop, inner_push_loop;
8871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Outer loop state: rax = current FrameDescription**, rdx = one past the
8881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // last FrameDescription**.
8891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movl(rdx, Operand(rax, Deoptimizer::output_count_offset()));
8901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rax, Operand(rax, Deoptimizer::output_offset()));
8911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ lea(rdx, Operand(rax, rdx, times_8, 0));
8921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&outer_push_loop);
8931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Inner loop state: rbx = current FrameDescription*, rcx = loop index.
8941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rbx, Operand(rax, 0));
8951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ movq(rcx, Operand(rbx, FrameDescription::frame_size_offset()));
8961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&inner_push_loop);
8971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ subq(rcx, Immediate(sizeof(intptr_t)));
8981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ push(Operand(rbx, rcx, times_1, FrameDescription::frame_content_offset()));
8991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ testq(rcx, rcx);
9001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(not_zero, &inner_push_loop);
9011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ addq(rax, Immediate(kPointerSize));
9021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ cmpq(rax, rdx);
9031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ j(below, &outer_push_loop);
9041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // In case of OSR, we have to restore the XMM registers.
9061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (type() == OSR) {
9071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) {
9081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
9091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      int src_offset = i * kDoubleSize + double_regs_offset;
9101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      __ movsd(xmm_reg, Operand(rbx, src_offset));
9111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
9121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
9131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Push state, pc, and continuation from the last output frame.
9151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  if (type() != OSR) {
9161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ push(Operand(rbx, FrameDescription::state_offset()));
9171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
9181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ push(Operand(rbx, FrameDescription::pc_offset()));
9191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ push(Operand(rbx, FrameDescription::continuation_offset()));
9201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Push the registers from the last output frame.
9221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < kNumberOfRegisters; i++) {
9231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = (i * kPointerSize) + FrameDescription::registers_offset();
9241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ push(Operand(rbx, offset));
9251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
9261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Restore the registers from the stack.
9281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = kNumberOfRegisters - 1; i >= 0 ; i--) {
9293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    Register r = Register::from_code(i);
9301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // Do not restore rsp, simply pop the value into the next register
9311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    // and overwrite this afterwards.
9321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    if (r.is(rsp)) {
9331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block      ASSERT(i > 0);
9343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      r = Register::from_code(i - 1);
9351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    }
9361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ pop(r);
9371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
9381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Set up the roots register.
940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ InitializeRootRegister();
941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch  __ InitializeSmiConstantRegister();
9421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Return to the continuation point.
9441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ ret(0);
945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::TableEntryGenerator::GeneratePrologue() {
9491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Create a sequence of deoptimization entries.
9501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Label done;
9511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = 0; i < count(); i++) {
9521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int start = masm()->pc_offset();
9531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    USE(start);
9541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ push_imm32(i);
9551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ jmp(&done);
9561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    ASSERT(masm()->pc_offset() - start == table_entry_size_);
9571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  }
9581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  __ bind(&done);
95981362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen}
96081362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen
9611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#undef __
9621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
9631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} }  // namespace v8::internal
965b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
966b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif  // V8_TARGET_ARCH_X64
967