1659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
2a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// Redistribution and use in source and binary forms, with or without
3a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// modification, are permitted provided that the following conditions are
4a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// met:
5a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//
6a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//     * Redistributions of source code must retain the above copyright
7a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//       notice, this list of conditions and the following disclaimer.
8a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//     * Redistributions in binary form must reproduce the above
9a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//       copyright notice, this list of conditions and the following
10a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//       disclaimer in the documentation and/or other materials provided
11a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//       with the distribution.
12a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//     * Neither the name of Google Inc. nor the names of its
13a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//       contributors may be used to endorse or promote products derived
14a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//       from this software without specific prior written permission.
15a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org//
16a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
28a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#include "v8.h"
29a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
30a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#include "codegen.h"
31a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#include "deoptimizer.h"
32a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#include "full-codegen.h"
33a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#include "safepoint-table.h"
34a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
35a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgnamespace v8 {
36a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgnamespace internal {
37a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
38169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.orgconst int Deoptimizer::table_entry_size_ = 12;
39a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
4031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
4131b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.orgint Deoptimizer::patch_size() {
4231b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  const int kCallInstructionSizeInWords = 3;
4331b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  return kCallInstructionSizeInWords * Assembler::kInstrSize;
4431b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org}
4531b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
4631b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
47fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.orgvoid Deoptimizer::PatchCodeForDeoptimization(Isolate* isolate, Code* code) {
4827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  Address code_start_address = code->instruction_start();
49a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Invalidate the relocation information, as it will become invalid by the
50a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // code patching below, and is not needed any more.
51a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  code->InvalidateRelocation();
52a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  // For each LLazyBailout instruction insert a call to the corresponding
5427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  // deoptimization entry.
5527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  DeoptimizationInputData* deopt_data =
5627bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      DeoptimizationInputData::cast(code->deoptimization_data());
57a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#ifdef DEBUG
5827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  Address prev_call_address = NULL;
59a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#endif
6027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
6127bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    if (deopt_data->Pc(i)->value() == -1) continue;
6227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    Address call_address = code_start_address + deopt_data->Pc(i)->value();
638432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Address deopt_entry = GetDeoptimizationEntry(isolate, i, LAZY);
64471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    // We need calls to have a predictable size in the unoptimized code, but
65471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    // this is optimized code, so we don't have to have a predictable size.
66471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    int call_size_in_bytes =
67471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org        MacroAssembler::CallSizeNotPredictableCodeSize(deopt_entry,
6859297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org                                                       RelocInfo::NONE32);
6927bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    int call_size_in_words = call_size_in_bytes / Assembler::kInstrSize;
7027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    ASSERT(call_size_in_bytes % Assembler::kInstrSize == 0);
7127bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    ASSERT(call_size_in_bytes <= patch_size());
7227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    CodePatcher patcher(call_address, call_size_in_words);
7359297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    patcher.masm()->Call(deopt_entry, RelocInfo::NONE32);
7427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    ASSERT(prev_call_address == NULL ||
7527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org           call_address >= prev_call_address + patch_size());
7627bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    ASSERT(call_address + patch_size() <= code->instruction_end());
77a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#ifdef DEBUG
7827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    prev_call_address = call_address;
79a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#endif
8027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  }
81a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
82a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
83a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
8488aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.orgstatic const int32_t kBranchBeforeInterrupt =  0x5a000004;
8588aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org
86e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// The back edge bookkeeping code matches the pattern:
87e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//
88e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//  <decrement profiling counter>
89e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//  2a 00 00 01       bpl ok
90e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//  e5 9f c? ??       ldr ip, [pc, <interrupt stub address>]
91e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//  e1 2f ff 3c       blx ip
92e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//  ok-label
93e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//
94e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org// We patch the code to the following form:
95e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//
96e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//  <decrement profiling counter>
97e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//  e1 a0 00 00       mov r0, r0 (NOP)
98e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//  e5 9f c? ??       ldr ip, [pc, <on-stack replacement address>]
99e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//  e1 2f ff 3c       blx ip
100e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org//  ok-label
101e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
102e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid Deoptimizer::PatchInterruptCodeAt(Code* unoptimized_code,
103e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                       Address pc_after,
104e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                       Code* interrupt_code,
105e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                       Code* replacement_code) {
106e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(!InterruptCodeIsPatched(unoptimized_code,
107e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                 pc_after,
108e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                 interrupt_code,
109e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                 replacement_code));
110e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  static const int kInstrSize = Assembler::kInstrSize;
111e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Turn the jump into nops.
11249edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  CodePatcher patcher(pc_after - 3 * kInstrSize, 1);
11349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org  patcher.masm()->nop();
114e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Replace the call address.
115e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  uint32_t interrupt_address_offset = Memory::uint16_at(pc_after -
11649edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      2 * kInstrSize) & 0xfff;
117e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Address interrupt_address_pointer = pc_after + interrupt_address_offset;
118e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Memory::uint32_at(interrupt_address_pointer) =
11949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org      reinterpret_cast<uint32_t>(replacement_code->entry());
120c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
121394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com  unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
122394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com      unoptimized_code, pc_after - 2 * kInstrSize, replacement_code);
123a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
124a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
125a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
126e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgvoid Deoptimizer::RevertInterruptCodeAt(Code* unoptimized_code,
127e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                        Address pc_after,
128e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                        Code* interrupt_code,
129e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                        Code* replacement_code) {
130e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(InterruptCodeIsPatched(unoptimized_code,
131e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                pc_after,
132e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                interrupt_code,
133e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                replacement_code));
134e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  static const int kInstrSize = Assembler::kInstrSize;
135e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Restore the original jump.
136e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CodePatcher patcher(pc_after - 3 * kInstrSize, 1);
137e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  patcher.masm()->b(4 * kInstrSize, pl);  // ok-label is 4 instructions later.
138e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT_EQ(kBranchBeforeInterrupt,
139e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org            Memory::int32_at(pc_after - 3 * kInstrSize));
140e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Restore the original call address.
141e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  uint32_t interrupt_address_offset = Memory::uint16_at(pc_after -
142e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      2 * kInstrSize) & 0xfff;
143e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Address interrupt_address_pointer = pc_after + interrupt_address_offset;
144e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Memory::uint32_at(interrupt_address_pointer) =
145e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      reinterpret_cast<uint32_t>(interrupt_code->entry());
146e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
147e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  interrupt_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch(
148e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      unoptimized_code, pc_after - 2 * kInstrSize, interrupt_code);
149e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org}
150e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
151e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org
152e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#ifdef DEBUG
153e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.orgbool Deoptimizer::InterruptCodeIsPatched(Code* unoptimized_code,
154394dbcf9009cf5203b6d85e8b515fcff072040f3erik.corry@gmail.com                                         Address pc_after,
155e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org                                         Code* interrupt_code,
15631b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org                                         Code* replacement_code) {
157e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  static const int kInstrSize = Assembler::kInstrSize;
15888aa058bdadfa79ae2836d12d6dd2d1c28aa490cdanno@chromium.org  ASSERT(Memory::int32_at(pc_after - kInstrSize) == kBlxIp);
15949edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
160e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  uint32_t interrupt_address_offset =
161e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org      Memory::uint16_at(pc_after - 2 * kInstrSize) & 0xfff;
162e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  Address interrupt_address_pointer = pc_after + interrupt_address_offset;
16349edbdf52640c88918f8e6638ab4965819eb1dfekmillikin@chromium.org
164e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  if (Assembler::IsNop(Assembler::instr_at(pc_after - 3 * kInstrSize))) {
165e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    ASSERT(Assembler::IsLdrPcImmediateOffset(
166e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        Assembler::instr_at(pc_after - 2 * kInstrSize)));
167e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    ASSERT(reinterpret_cast<uint32_t>(replacement_code->entry()) ==
168e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org           Memory::uint32_at(interrupt_address_pointer));
169e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    return true;
170e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  } else {
171e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    ASSERT(Assembler::IsLdrPcImmediateOffset(
172e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org        Assembler::instr_at(pc_after - 2 * kInstrSize)));
173e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    ASSERT_EQ(kBranchBeforeInterrupt,
174e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org              Memory::int32_at(pc_after - 3 * kInstrSize));
175e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    ASSERT(reinterpret_cast<uint32_t>(interrupt_code->entry()) ==
176e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org           Memory::uint32_at(interrupt_address_pointer));
177e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    return false;
178e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  }
179a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
180e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org#endif  // DEBUG
181a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
182a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
183471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.orgstatic int LookupBailoutId(DeoptimizationInputData* data, BailoutId ast_id) {
184496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  ByteArray* translations = data->TranslationByteArray();
185496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  int length = data->DeoptCount();
186496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  for (int i = 0; i < length; i++) {
187471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org    if (data->AstId(i) == ast_id) {
188496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      TranslationIterator it(translations,  data->TranslationIndex(i)->value());
189496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      int value = it.Next();
190496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      ASSERT(Translation::BEGIN == static_cast<Translation::Opcode>(value));
191496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      // Read the number of frames.
192496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      value = it.Next();
193496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      if (value == 1) return i;
194496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    }
195496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  }
196496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  UNREACHABLE();
197496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  return -1;
198496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org}
199496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
200496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
201a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Deoptimizer::DoComputeOsrOutputFrame() {
202496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  DeoptimizationInputData* data = DeoptimizationInputData::cast(
203a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      compiled_code_->deoptimization_data());
204496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned ast_id = data->OsrAstId()->value();
205496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
206471f2f1d24adb4bad1edc3bf0ee35092486de187mstarzinger@chromium.org  int bailout_id = LookupBailoutId(data, BailoutId(ast_id));
207496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned translation_index = data->TranslationIndex(bailout_id)->value();
208496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  ByteArray* translations = data->TranslationByteArray();
209496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
210496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  TranslationIterator iterator(translations, translation_index);
211496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  Translation::Opcode opcode =
212496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      static_cast<Translation::Opcode>(iterator.Next());
213496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  ASSERT(Translation::BEGIN == opcode);
214496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  USE(opcode);
215496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  int count = iterator.Next();
216659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org  iterator.Skip(1);  // Drop JS frame count.
217496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  ASSERT(count == 1);
218496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  USE(count);
219496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
220496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  opcode = static_cast<Translation::Opcode>(iterator.Next());
221496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  USE(opcode);
222659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org  ASSERT(Translation::JS_FRAME == opcode);
223496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned node_id = iterator.Next();
224496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  USE(node_id);
225496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  ASSERT(node_id == ast_id);
2265a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  int closure_id = iterator.Next();
2275a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  USE(closure_id);
2285a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org  ASSERT_EQ(Translation::kSelfLiteralId, closure_id);
229496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned height = iterator.Next();
230496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned height_in_bytes = height * kPointerSize;
231496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  USE(height_in_bytes);
232496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
233496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned fixed_size = ComputeFixedSize(function_);
234496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned input_frame_size = input_->GetFrameSize();
235496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  ASSERT(fixed_size + height_in_bytes == input_frame_size);
236496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
237a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  unsigned stack_slot_size = compiled_code_->stack_slots() * kPointerSize;
238496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value();
239496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned outgoing_size = outgoing_height * kPointerSize;
240496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size;
241496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  ASSERT(outgoing_size == 0);  // OSR does not happen in the middle of a call.
242496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
243496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  if (FLAG_trace_osr) {
244496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ",
245496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org           reinterpret_cast<intptr_t>(function_));
2464e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    PrintFunctionName();
247496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    PrintF(" => node=%u, frame=%d->%d]\n",
248496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org           ast_id,
249496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org           input_frame_size,
250496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org           output_frame_size);
251496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  }
252496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
253496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // There's only one output frame in the OSR case.
254496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  output_count_ = 1;
255496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  output_ = new FrameDescription*[1];
256496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  output_[0] = new(output_frame_size) FrameDescription(
257496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      output_frame_size, function_);
258659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org  output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT);
259496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
260496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // Clear the incoming parameters in the optimized frame to avoid
261496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // confusing the garbage collector.
262496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  unsigned output_offset = output_frame_size - kPointerSize;
263496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  int parameter_count = function_->shared()->formal_parameter_count() + 1;
264496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  for (int i = 0; i < parameter_count; ++i) {
265496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    output_[0]->SetFrameSlot(output_offset, 0);
266496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    output_offset -= kPointerSize;
267496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  }
268496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
269496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // Translate the incoming parameters. This may overwrite some of the
270496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // incoming argument slots we've just cleared.
271496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  int input_offset = input_frame_size - kPointerSize;
272496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  bool ok = true;
273496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  int limit = input_offset - (parameter_count * kPointerSize);
274496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  while (ok && input_offset > limit) {
275496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    ok = DoOsrTranslateCommand(&iterator, &input_offset);
276496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  }
277496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
278496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // There are no translation commands for the caller's pc and fp, the
279496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // context, and the function.  Set them up explicitly.
2807516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org  for (int i =  StandardFrameConstants::kCallerPCOffset;
2817516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org       ok && i >=  StandardFrameConstants::kMarkerOffset;
2827516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org       i -= kPointerSize) {
283496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    uint32_t input_value = input_->GetFrameSlot(input_offset);
284496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    if (FLAG_trace_osr) {
2857516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      const char* name = "UNKNOWN";
2867516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      switch (i) {
2877516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org        case StandardFrameConstants::kCallerPCOffset:
2887516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          name = "caller's pc";
2897516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          break;
2907516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org        case StandardFrameConstants::kCallerFPOffset:
2917516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          name = "fp";
2927516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          break;
2937516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org        case StandardFrameConstants::kContextOffset:
2947516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          name = "context";
2957516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          break;
2967516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org        case StandardFrameConstants::kMarkerOffset:
2977516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          name = "function";
2987516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org          break;
2997516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      }
3007516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org      PrintF("    [sp + %d] <- 0x%08x ; [sp + %d] (fixed part - %s)\n",
301496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org             output_offset,
302496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org             input_value,
3037516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org             input_offset,
3047516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org             name);
305496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    }
3067516f05132429850aa326421ed3e25f23b4c071blrn@chromium.org
307496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset));
308496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    input_offset -= kPointerSize;
309496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    output_offset -= kPointerSize;
310496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  }
311496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
312496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // Translate the rest of the frame.
313496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  while (ok && input_offset >= 0) {
314496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    ok = DoOsrTranslateCommand(&iterator, &input_offset);
315496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  }
316496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
317496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  // If translation of any command failed, continue using the input frame.
318496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  if (!ok) {
319496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    delete output_[0];
320496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    output_[0] = input_;
321496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    output_[0]->SetPc(reinterpret_cast<uint32_t>(from_));
322496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  } else {
323f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com    // Set up the frame pointer and the context pointer.
324496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    output_[0]->SetRegister(fp.code(), input_->GetRegister(fp.code()));
325496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    output_[0]->SetRegister(cp.code(), input_->GetRegister(cp.code()));
326496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
327496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    unsigned pc_offset = data->OsrPcOffset()->value();
328496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    uint32_t pc = reinterpret_cast<uint32_t>(
329a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        compiled_code_->entry() + pc_offset);
330496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    output_[0]->SetPc(pc);
331496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  }
3327979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Code* continuation = isolate_->builtins()->builtin(Builtins::kNotifyOSR);
333496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  output_[0]->SetContinuation(
334496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org      reinterpret_cast<uint32_t>(continuation->entry()));
335496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org
336496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  if (FLAG_trace_osr) {
337496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ",
338496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org           ok ? "finished" : "aborted",
3395a11aaf63fdb7843c9b116fdb84ee35b0a980ea6yangguo@chromium.org           reinterpret_cast<intptr_t>(function_));
3404e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org    PrintFunctionName();
341496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org    PrintF(" => pc=0x%0x]\n", output_[0]->GetPc());
342496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org  }
343a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
344a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
345a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
3464f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgvoid Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
3474f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Set the register values. The values are not important as there are no
3484f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // callee saved registers in JavaScript frames, so all registers are
3494f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // spilled. Registers fp and sp are set to the correct values though.
3504f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
3514f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  for (int i = 0; i < Register::kNumRegisters; i++) {
3524f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    input_->SetRegister(i, i * 4);
3534f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
3544f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp()));
3554f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp()));
356a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) {
3574f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    input_->SetDoubleRegister(i, 0.0);
3584f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
359a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
3604f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Fill the frame content from the actual data on the frame.
3614f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) {
3624f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    input_->SetFrameSlot(i, Memory::uint32_at(tos + i));
3634f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
3644f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
3654f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
3664f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
3676e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.orgvoid Deoptimizer::SetPlatformCompiledStubRegisters(
3686e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org    FrameDescription* output_frame, CodeStubInterfaceDescriptor* descriptor) {
3696e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  ApiFunction function(descriptor->deoptimization_handler_);
3706e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  ExternalReference xref(&function, ExternalReference::BUILTIN_CALL, isolate_);
3716e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  intptr_t handler = reinterpret_cast<intptr_t>(xref.address());
3726e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  int params = descriptor->register_param_count_;
3736e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  if (descriptor->stack_parameter_count_ != NULL) {
3746e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org    params++;
3756e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  }
3766e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  output_frame->SetRegister(r0.code(), params);
3776e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  output_frame->SetRegister(r1.code(), handler);
3786e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org}
3796e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
3806e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
3816e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.orgvoid Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
3826e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; ++i) {
3836e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org    double double_value = input_->GetDoubleRegister(i);
3846e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org    output_frame->SetDoubleRegister(i, double_value);
3856e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  }
3866e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org}
3876e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
3886e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
3894e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.orgbool Deoptimizer::HasAlignmentPadding(JSFunction* function) {
3904e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  // There is no dynamic alignment padding on ARM in the input frame.
3914e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  return false;
3924e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org}
3934e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
3944e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
3954f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org#define __ masm()->
396a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
397a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// This code tries to be close to ia32 code so that any changes can be
398a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org// easily ported.
399a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Deoptimizer::EntryGenerator::Generate() {
400a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  GeneratePrologue();
401ea88ce93dcb41a9200ec8747ae7642a5db1f4ce7sgjesse@chromium.org
402a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Save all general purpose registers before messing with them.
403a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  const int kNumberOfRegisters = Register::kNumRegisters;
404a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
405a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Everything but pc, lr and ip which will be saved but not restored.
406a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  RegList restored_regs = kJSCallerSaved | kCalleeSaved | ip.bit();
407a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
408a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  const int kDoubleRegsSize =
409a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      kDoubleSize * DwVfpRegister::kMaxNumAllocatableRegisters;
410a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
411e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Save all allocatable VFP registers before messing with them.
412e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(kDoubleRegZero.code() == 14);
413e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  ASSERT(kScratchDoubleReg.code() == 15);
414003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org
415e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Check CPU flags for number of registers, setting the Z condition flag.
416e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ CheckFor32DRegs(ip);
417003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org
418e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Push registers d0-d13, and possibly d16-d31, on the stack.
419e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // If d16-d31 are not pushed, decrease the stack pointer instead.
420e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vstm(db_w, sp, d16, d31, ne);
421e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ sub(sp, sp, Operand(16 * kDoubleSize), LeaveCC, eq);
422e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ vstm(db_w, sp, d0, d13);
423a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
424a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Push all 16 registers (needed to populate FrameDescription::registers_).
4254acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  // TODO(1588) Note that using pc with stm is deprecated, so we should perhaps
4264acdc2c8d4caecf7606db8af710366c1d6e28fe5whesse@chromium.org  // handle this a bit differently.
427a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ stm(db_w, sp, restored_regs  | sp.bit() | lr.bit() | pc.bit());
428a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
429a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  const int kSavedRegistersAreaSize =
430a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org      (kNumberOfRegisters * kPointerSize) + kDoubleRegsSize;
431a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
432a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Get the bailout id from the stack.
433a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r2, MemOperand(sp, kSavedRegistersAreaSize));
434a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
435169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Get the address of the location in the code object (r3) (return
436a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // address for lazy deoptimization) and compute the fp-to-sp delta in
437a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // register r4.
438169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ mov(r3, lr);
439169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Correct one word for bailout id.
440169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ add(r4, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
441a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ sub(r4, fp, r4);
442a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
443a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Allocate a new deoptimizer object.
444a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Pass four arguments in r0 to r3 and fifth argument on stack.
445c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ PrepareCallCFunction(6, r5);
446a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
447a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(r1, Operand(type()));  // bailout type,
448a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r2: bailout id already loaded.
449a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r3: code address or 0 already loaded.
450a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ str(r4, MemOperand(sp, 0 * kPointerSize));  // Fp-to-sp delta.
45132d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org  __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
452c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ str(r5, MemOperand(sp, 1 * kPointerSize));  // Isolate.
453a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Call Deoptimizer::New().
454c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
455c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    AllowExternalCallThatCantCauseGC scope(masm());
45632d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate()), 6);
457c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
458a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
459a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Preserve "deoptimizer" object in register r0 and get the input
460a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // frame descriptor pointer to r1 (deoptimizer->input_);
461a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r1, MemOperand(r0, Deoptimizer::input_offset()));
462a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
463a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Copy core registers into FrameDescription::registers_[kNumRegisters].
464a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  ASSERT(Register::kNumRegisters == kNumberOfRegisters);
465c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  for (int i = 0; i < kNumberOfRegisters; i++) {
466c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org    int offset = (i * kPointerSize) + FrameDescription::registers_offset();
467c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org    __ ldr(r2, MemOperand(sp, i * kPointerSize));
468c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org    __ str(r2, MemOperand(r1, offset));
469c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  }
470a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
471e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Copy VFP registers to
472e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // double_registers_[DoubleRegister::kMaxNumAllocatableRegisters]
473e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int double_regs_offset = FrameDescription::double_registers_offset();
474e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  for (int i = 0; i < DwVfpRegister::kMaxNumAllocatableRegisters; ++i) {
475e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    int dst_offset = i * kDoubleSize + double_regs_offset;
476e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize;
477e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ vldr(d0, sp, src_offset);
478e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ vstr(d0, r1, dst_offset);
479c54d36599f1e72bddd09d5b7a980304c7b638048ricow@chromium.org  }
480a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
481169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Remove the bailout id and the saved registers from the stack.
482169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ add(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize)));
483a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
484a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Compute a pointer to the unwinding limit in register r2; that is
485a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // the first stack slot not part of the input frame.
486a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r2, MemOperand(r1, FrameDescription::frame_size_offset()));
487a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ add(r2, r2, sp);
488a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
489a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Unwind the stack down to - but not including - the unwinding
490a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // limit and copy the contents of the activation frame to the input
491a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // frame description.
492a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ add(r3,  r1, Operand(FrameDescription::frame_content_offset()));
493a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label pop_loop;
494a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Label pop_loop_header;
495a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ b(&pop_loop_header);
496a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&pop_loop);
497a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ pop(r4);
498a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ str(r4, MemOperand(r3, 0));
499a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ add(r3, r3, Operand(sizeof(uint32_t)));
500a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ bind(&pop_loop_header);
501a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ cmp(r2, sp);
502a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ b(ne, &pop_loop);
503a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
504a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Compute the output frame in the deoptimizer.
505a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ push(r0);  // Preserve deoptimizer object across call.
506a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r0: deoptimizer object; r1: scratch.
507a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ PrepareCallCFunction(1, r1);
508a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Call Deoptimizer::ComputeOutputFrames().
509c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
510c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    AllowExternalCallThatCantCauseGC scope(masm());
511c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallCFunction(
51232d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        ExternalReference::compute_output_frames_function(isolate()), 1);
513c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
514a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ pop(r0);  // Restore deoptimizer object (class Deoptimizer).
515a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
516a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Replace the current (input) frame with the output frames.
517a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Label outer_push_loop, inner_push_loop,
518a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      outer_loop_header, inner_loop_header;
519e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org  // Outer loop state: r4 = current "FrameDescription** output_",
520a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // r1 = one past the last FrameDescription**.
521a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r1, MemOperand(r0, Deoptimizer::output_count_offset()));
522e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org  __ ldr(r4, MemOperand(r0, Deoptimizer::output_offset()));  // r4 is output_.
523e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org  __ add(r1, r4, Operand(r1, LSL, 2));
524a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ jmp(&outer_loop_header);
525a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&outer_push_loop);
526a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Inner loop state: r2 = current FrameDescription*, r3 = loop index.
527e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org  __ ldr(r2, MemOperand(r4, 0));  // output_[ix]
528a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r3, MemOperand(r2, FrameDescription::frame_size_offset()));
529a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ jmp(&inner_loop_header);
530a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&inner_push_loop);
531a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ sub(r3, r3, Operand(sizeof(uint32_t)));
532a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ add(r6, r2, Operand(r3));
533a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r7, MemOperand(r6, FrameDescription::frame_content_offset()));
534a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ push(r7);
535a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ bind(&inner_loop_header);
53659297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  __ cmp(r3, Operand::Zero());
537a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ b(ne, &inner_push_loop);  // test for gt?
538e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org  __ add(r4, r4, Operand(kPointerSize));
539a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ bind(&outer_loop_header);
540e3b8d0fe80e858c990832db1233c069f8b8cd5c9mstarzinger@chromium.org  __ cmp(r4, r1);
541a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ b(lt, &outer_push_loop);
542a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
543e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  // Check CPU flags for number of registers, setting the Z condition flag.
544e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ CheckFor32DRegs(ip);
54594b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org
546e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  __ ldr(r1, MemOperand(r0, Deoptimizer::input_offset()));
547e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  int src_offset = FrameDescription::double_registers_offset();
548e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  for (int i = 0; i < DwVfpRegister::kMaxNumRegisters; ++i) {
549e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (i == kDoubleRegZero.code()) continue;
550e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    if (i == kScratchDoubleReg.code()) continue;
55194b0d6fcb08a2f01ba52c6edb712068f482366f1danno@chromium.org
552e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    const DwVfpRegister reg = DwVfpRegister::from_code(i);
553e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    __ vldr(reg, r1, src_offset, i < 16 ? al : ne);
554e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org    src_offset += kDoubleSize;
555003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org  }
556003650ee766f5e92756d470a37973fd371757485yangguo@chromium.org
557a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Push state, pc, and continuation from the last output frame.
558a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  if (type() != OSR) {
559a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ ldr(r6, MemOperand(r2, FrameDescription::state_offset()));
560a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ push(r6);
561a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
562a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
563a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r6, MemOperand(r2, FrameDescription::pc_offset()));
564a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ push(r6);
565a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldr(r6, MemOperand(r2, FrameDescription::continuation_offset()));
566a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ push(r6);
567a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
568a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Push the registers from the last output frame.
569a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
5700ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    int offset = (i * kPointerSize) + FrameDescription::registers_offset();
571a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ ldr(r6, MemOperand(r2, offset));
572a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ push(r6);
573a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
574a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
575a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Restore the registers from the stack.
576a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ldm(ia_w, sp, restored_regs);  // all but pc registers.
577a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ pop(ip);  // remove sp
578a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ pop(ip);  // remove lr
579a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
580f2038fb01417bcf7698b87a5dfaa4a861539618aerik.corry@gmail.com  __ InitializeRootRegister();
581a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
582a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ pop(ip);  // remove pc
583a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ pop(r7);  // get continuation, leave pc on stack
584a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ pop(lr);
585a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ Jump(r7);
586a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ stop("Unreachable.");
587a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
588a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
589a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
590a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Deoptimizer::TableEntryGenerator::GeneratePrologue() {
591169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Create a sequence of deoptimization entries.
592169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Note that registers are still live when jumping to an entry.
593a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label done;
594a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  for (int i = 0; i < count(); i++) {
595a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    int start = masm()->pc_offset();
596a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    USE(start);
597a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ mov(ip, Operand(i));
598a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ push(ip);
599a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ b(&done);
600a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    ASSERT(masm()->pc_offset() - start == table_entry_size_);
601a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
602a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&done);
603a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
604a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
605c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
606c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgvoid FrameDescription::SetCallerPc(unsigned offset, intptr_t value) {
607c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  SetFrameSlot(offset, value);
608c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org}
609c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
610c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
611c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgvoid FrameDescription::SetCallerFp(unsigned offset, intptr_t value) {
612c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  SetFrameSlot(offset, value);
613c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org}
614c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
615c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
616a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#undef __
617a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
618a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} }  // namespace v8::internal
619