13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved.
2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file.
4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_IA32
6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h"
8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/deoptimizer.h"
9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/full-codegen/full-codegen.h"
10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/ia32/frames-ia32.h"
11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/register-configuration.h"
12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/safepoint-table.h"
13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 {
15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal {
16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochconst int Deoptimizer::table_entry_size_ = 10;
18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Deoptimizer::patch_size() {
211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  return Assembler::kCallInstructionLength;
221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block}
231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
2544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
2644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  Isolate* isolate = code->GetIsolate();
2744f0eee88ff00398ff7f715fab053374d808c90dSteve Block  HandleScope scope(isolate);
2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block
2944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // Compute the size of relocation information needed for the code
30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier  // patching in Deoptimizer::PatchCodeForDeoptimization below.
3144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int min_reloc_size = 0;
322b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  int prev_pc_offset = 0;
332b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  DeoptimizationInputData* deopt_data =
342b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch      DeoptimizationInputData::cast(code->deoptimization_data());
352b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
362b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    int pc_offset = deopt_data->Pc(i)->value();
372b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    if (pc_offset == -1) continue;
38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_GE(pc_offset, prev_pc_offset);
392b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    int pc_delta = pc_offset - prev_pc_offset;
402b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    // We use RUNTIME_ENTRY reloc info which has a size of 2 bytes
412b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    // if encodable with small pc delta encoding and up to 6 bytes
422b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    // otherwise.
432b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    if (pc_delta <= RelocInfo::kMaxSmallPCDelta) {
442b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch      min_reloc_size += 2;
452b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    } else {
462b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch      min_reloc_size += 6;
4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
482b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    prev_pc_offset = pc_offset;
4944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // If the relocation information is not big enough we create a new
5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // relocation info object that is padded with comments to make it
5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  // big enough for lazy doptimization.
5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  int reloc_length = code->relocation_info()->length();
5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  if (min_reloc_size > reloc_length) {
5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int comment_reloc_size = RelocInfo::kMinRelocCommentSize;
5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Padding needed.
5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int min_padding = min_reloc_size - reloc_length;
5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Number of comments needed to take up at least that much space.
6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int additional_comments =
6144f0eee88ff00398ff7f715fab053374d808c90dSteve Block        (min_padding + comment_reloc_size - 1) / comment_reloc_size;
6244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Actual padding size.
6344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    int padding = additional_comments * comment_reloc_size;
6444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Allocate new relocation info and copy old relocation to the end
6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // of the new relocation info array because relocation info is
6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // written and read backwards.
6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Factory* factory = isolate->factory();
6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    Handle<ByteArray> new_reloc =
6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block        factory->NewByteArray(reloc_length + padding, TENURED);
70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    MemCopy(new_reloc->GetDataStartAddress() + padding,
71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch            code->relocation_info()->GetDataStartAddress(), reloc_length);
7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Create a relocation writer to write the comments in the padding
7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // space. Use position 0 for everything to ensure short encoding.
7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block    RelocInfoWriter reloc_info_writer(
7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block        new_reloc->GetDataStartAddress() + padding, 0);
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    intptr_t comment_string
7744f0eee88ff00398ff7f715fab053374d808c90dSteve Block        = reinterpret_cast<intptr_t>(RelocInfo::kFillerCommentString);
78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    RelocInfo rinfo(isolate, 0, RelocInfo::COMMENT, comment_string, NULL);
7944f0eee88ff00398ff7f715fab053374d808c90dSteve Block    for (int i = 0; i < additional_comments; ++i) {
8044f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef DEBUG
8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block      byte* pos_before = reloc_info_writer.pos();
8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
8344f0eee88ff00398ff7f715fab053374d808c90dSteve Block      reloc_info_writer.Write(&rinfo);
84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      DCHECK(RelocInfo::kMinRelocCommentSize ==
8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block             pos_before - reloc_info_writer.pos());
8644f0eee88ff00398ff7f715fab053374d808c90dSteve Block    }
8744f0eee88ff00398ff7f715fab053374d808c90dSteve Block    // Replace relocation information on the code object.
8844f0eee88ff00398ff7f715fab053374d808c90dSteve Block    code->set_relocation_info(*new_reloc);
8944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  }
9044f0eee88ff00398ff7f715fab053374d808c90dSteve Block}
9144f0eee88ff00398ff7f715fab053374d808c90dSteve Block
92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Deoptimizer::PatchCodeForDeoptimization(Isolate* isolate, Code* code) {
941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Address code_start_address = code->instruction_start();
951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_zap_code_space) {
97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    // Fail hard and early if we enter this code object again.
98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    byte* pointer = code->FindCodeAgeSequence();
99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (pointer != NULL) {
100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      pointer += kNoCodeAgeSequenceLength;
101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    } else {
102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      pointer = code->instruction_start();
103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
104014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CodePatcher patcher(isolate, pointer, 1);
105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->int3();
106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DeoptimizationInputData* data =
108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        DeoptimizationInputData::cast(code->deoptimization_data());
109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    int osr_offset = data->OsrPcOffset()->value();
110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    if (osr_offset > 0) {
111014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      CodePatcher osr_patcher(isolate, code->instruction_start() + osr_offset,
112014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                              1);
113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      osr_patcher.masm()->int3();
114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    }
115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // We will overwrite the code's relocation info in-place. Relocation info
1181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // is written backward. The relocation info is the payload of a byte
1191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // array.  Later on we will slide this to the start of the byte array and
1201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // create a filler object in the remaining space.
1211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  ByteArray* reloc_info = code->relocation_info();
1221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  Address reloc_end_address = reloc_info->address() + reloc_info->Size();
1231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  RelocInfoWriter reloc_info_writer(reloc_end_address, code_start_address);
1241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1252b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  // Since the call is a relative encoding, write new
1261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // reloc info.  We do not need any of the existing reloc info because the
1271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // existing code will not be used again (we zap it in debug builds).
1282b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  //
1292b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  // Emit call to lazy deoptimization at all lazy deopt points.
1302b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  DeoptimizationInputData* deopt_data =
1312b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch      DeoptimizationInputData::cast(code->deoptimization_data());
1322b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch#ifdef DEBUG
1332b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  Address prev_call_address = NULL;
1342b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch#endif
135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // For each LLazyBailout instruction insert a call to the corresponding
136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // deoptimization entry.
1372b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
1382b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    if (deopt_data->Pc(i)->value() == -1) continue;
1392b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    // Patch lazy deoptimization entry.
1402b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    Address call_address = code_start_address + deopt_data->Pc(i)->value();
141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    CodePatcher patcher(isolate, call_address, patch_size());
142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    Address deopt_entry = GetDeoptimizationEntry(isolate, i, LAZY);
143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    patcher.masm()->call(deopt_entry, RelocInfo::NONE32);
1442b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    // We use RUNTIME_ENTRY for deoptimization bailouts.
145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    RelocInfo rinfo(isolate, call_address + 1,  // 1 after the call opcode.
1462b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch                    RelocInfo::RUNTIME_ENTRY,
147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch                    reinterpret_cast<intptr_t>(deopt_entry), NULL);
1482b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    reloc_info_writer.Write(&rinfo);
149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK_GE(reloc_info_writer.pos(),
1502b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch              reloc_info->address() + ByteArray::kHeaderSize);
151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(prev_call_address == NULL ||
1522b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch           call_address >= prev_call_address + patch_size());
153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(call_address + patch_size() <= code->instruction_end());
1542b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch#ifdef DEBUG
1552b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch    prev_call_address = call_address;
1562b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch#endif
157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
1581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block
1591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  // Move the relocation info to the beginning of the byte array.
160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const int new_reloc_length = reloc_end_address - reloc_info_writer.pos();
161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  MemMove(code->relocation_start(), reloc_info_writer.pos(), new_reloc_length);
162014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
163014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // Right trim the relocation info to free up remaining space.
164014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const int delta = reloc_info->length() - new_reloc_length;
165014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  if (delta > 0) {
166014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    isolate->heap()->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(
167014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch        reloc_info, delta);
168014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  }
169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
1723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
1733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Set the register values. The values are not important as there are no
1743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // callee saved registers in JavaScript frames, so all registers are
1753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // spilled. Registers ebp and esp are set to the correct values though.
1763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (int i = 0; i < Register::kNumRegisters; i++) {
1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    input_->SetRegister(i, i * 4);
1793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp()));
1813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp()));
182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < XMMRegister::kMaxNumRegisters; i++) {
1833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    input_->SetDoubleRegister(i, 0.0);
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Fill the frame content from the actual data on the frame.
1873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) {
1883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    input_->SetFrameSlot(i, Memory::uint32_at(tos + i));
1893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  }
1903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch}
1913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Deoptimizer::SetPlatformCompiledStubRegisters(
194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    FrameDescription* output_frame, CodeStubDescriptor* descriptor) {
195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  intptr_t handler =
196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      reinterpret_cast<intptr_t>(descriptor->deoptimization_handler());
197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int params = descriptor->GetHandlerParameterCount();
198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  output_frame->SetRegister(eax.code(), params);
199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  output_frame->SetRegister(ebx.code(), handler);
200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < XMMRegister::kMaxNumRegisters; ++i) {
205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    double double_value = input_->GetDoubleRegister(i);
206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    output_frame->SetDoubleRegister(i, double_value);
207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool Deoptimizer::HasAlignmentPadding(JSFunction* function) {
212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  int parameter_count =
213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      function->shared()->internal_formal_parameter_count() + 1;
214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned input_frame_size = input_->GetFrameSize();
215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  unsigned alignment_state_offset =
216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      input_frame_size - parameter_count * kPointerSize -
217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      StandardFrameConstants::kFixedFrameSize -
218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      kPointerSize;
219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  DCHECK(JavaScriptFrameConstants::kDynamicAlignmentStateOffset ==
220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      JavaScriptFrameConstants::kLocal0Offset);
221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  int32_t alignment_state = input_->GetFrameSlot(alignment_state_offset);
222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  return (alignment_state == kAlignmentPaddingPushed);
223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define __ masm()->
227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Deoptimizer::TableEntryGenerator::Generate() {
229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  GeneratePrologue();
23044f0eee88ff00398ff7f715fab053374d808c90dSteve Block
231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Save all general purpose registers before messing with them.
232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const int kNumberOfRegisters = Register::kNumRegisters;
233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const int kDoubleRegsSize = kDoubleSize * XMMRegister::kMaxNumRegisters;
2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(esp, Immediate(kDoubleRegsSize));
236014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  const RegisterConfiguration* config =
237014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch      RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT);
238014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
239014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int code = config->GetAllocatableDoubleCode(i);
240014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister xmm_reg = XMMRegister::from_code(code);
241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int offset = code * kDoubleSize;
242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(Operand(esp, offset), xmm_reg);
243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ pushad();
246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
247014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate());
248014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  __ mov(Operand::StaticVariable(c_entry_fp_address), ebp);
249014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch
250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize +
251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch                                      kDoubleRegsSize;
252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Get the bailout id from the stack.
254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(ebx, Operand(esp, kSavedRegistersAreaSize));
255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Get the address of the location in the code object
257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // and compute the fp-to-sp delta in register edx.
258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ mov(ecx, Operand(esp, kSavedRegistersAreaSize + 1 * kPointerSize));
259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ lea(edx, Operand(esp, kSavedRegistersAreaSize + 2 * kPointerSize));
260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
2613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(edx, ebp);
262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ neg(edx);
263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Allocate a new deoptimizer object.
2658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ PrepareCallCFunction(6, eax);
266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(Operand(esp, 0 * kPointerSize), eax);  // Function.
268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(Operand(esp, 1 * kPointerSize), Immediate(type()));  // Bailout type.
269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(Operand(esp, 2 * kPointerSize), ebx);  // Bailout id.
270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(Operand(esp, 3 * kPointerSize), ecx);  // Code address or 0.
271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(Operand(esp, 4 * kPointerSize), edx);  // Fp-to-sp delta.
2728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  __ mov(Operand(esp, 5 * kPointerSize),
273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Immediate(ExternalReference::isolate_address(isolate())));
2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
2753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AllowExternalCallThatCantCauseGC scope(masm());
276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate()), 6);
2773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Preserve deoptimizer object in register eax and get the input
280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // frame descriptor pointer.
281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(ebx, Operand(eax, Deoptimizer::input_offset()));
282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Fill in the input registers.
2841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block  for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
2851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = (i * kPointerSize) + FrameDescription::registers_offset();
2861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    __ pop(Operand(ebx, offset));
287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  int double_regs_offset = FrameDescription::double_registers_offset();
290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Fill in the double input registers.
291014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
292014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int code = config->GetAllocatableDoubleCode(i);
293014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int dst_offset = code * kDoubleSize + double_regs_offset;
294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int src_offset = code * kDoubleSize;
295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(xmm0, Operand(esp, src_offset));
296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(Operand(ebx, dst_offset), xmm0);
297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Clear FPU all exceptions.
300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // TODO(ulan): Find out why the TOP register is not zero here in some cases,
301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // and check that the generated code never deoptimizes with unbalanced stack.
302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ fnclex();
303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // Remove the bailout id, return address and the double registers.
305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize));
306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compute a pointer to the unwinding limit in register ecx; that is
308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // the first stack slot not part of the input frame.
309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset()));
3103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(ecx, esp);
311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Unwind the stack down to - but not including - the unwinding
313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // limit and copy the contents of the activation frame to the input
314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // frame description.
315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset()));
316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label pop_loop_header;
317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&pop_loop_header);
318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label pop_loop;
319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&pop_loop);
320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ pop(Operand(edx, 0));
3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(edx, Immediate(sizeof(uint32_t)));
322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&pop_loop_header);
3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(ecx, esp);
324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ j(not_equal, &pop_loop);
325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Compute the output frame in the deoptimizer.
327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(eax);
328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ PrepareCallCFunction(1, ebx);
329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(Operand(esp, 0 * kPointerSize), eax);
3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  {
3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    AllowExternalCallThatCantCauseGC scope(masm());
3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    __ CallCFunction(
333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch        ExternalReference::compute_output_frames_function(isolate()), 1);
3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  }
335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ pop(eax);
336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // If frame was dynamically aligned, pop padding.
338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label no_padding;
339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()),
340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch         Immediate(0));
341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ j(equal, &no_padding);
342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ pop(ecx);
343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  if (FLAG_debug_code) {
344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ cmp(ecx, Immediate(kAlignmentZapValue));
345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ Assert(equal, kAlignmentMarkerExpected);
346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  }
347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&no_padding);
348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Replace the current frame with the output frames.
350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  Label outer_push_loop, inner_push_loop,
351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch      outer_loop_header, inner_loop_header;
352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Outer loop state: eax = current FrameDescription**, edx = one past the
353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // last FrameDescription**.
354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(edx, Operand(eax, Deoptimizer::output_count_offset()));
355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(eax, Operand(eax, Deoptimizer::output_offset()));
356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ lea(edx, Operand(eax, edx, times_4, 0));
357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&outer_loop_header);
358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&outer_push_loop);
359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Inner loop state: ebx = current FrameDescription*, ecx = loop index.
360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(ebx, Operand(eax, 0));
361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset()));
362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ jmp(&inner_loop_header);
363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&inner_push_loop);
3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ sub(ecx, Immediate(sizeof(uint32_t)));
365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset()));
366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&inner_loop_header);
3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ test(ecx, ecx);
368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ j(not_zero, &inner_push_loop);
3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ add(eax, Immediate(kPointerSize));
370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ bind(&outer_loop_header);
3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  __ cmp(eax, edx);
372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ j(below, &outer_push_loop);
373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  // In case of a failed STUB, we have to restore the XMM registers.
375014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  for (int i = 0; i < config->num_allocatable_double_registers(); ++i) {
376014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int code = config->GetAllocatableDoubleCode(i);
377014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    XMMRegister xmm_reg = XMMRegister::from_code(code);
378014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch    int src_offset = code * kDoubleSize + double_regs_offset;
379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    __ movsd(xmm_reg, Operand(ebx, src_offset));
380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Push state, pc, and continuation from the last output frame.
383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  __ push(Operand(ebx, FrameDescription::state_offset()));
384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(Operand(ebx, FrameDescription::pc_offset()));
385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ push(Operand(ebx, FrameDescription::continuation_offset()));
386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Push the registers from the last output frame.
389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < kNumberOfRegisters; i++) {
3901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block    int offset = (i * kPointerSize) + FrameDescription::registers_offset();
391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ push(Operand(ebx, offset));
392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Restore the registers from the stack.
395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ popad();
396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Return to the continuation point.
398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ ret(0);
399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::TableEntryGenerator::GeneratePrologue() {
403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  // Create a sequence of deoptimization entries.
404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  Label done;
405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  for (int i = 0; i < count(); i++) {
406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    int start = masm()->pc_offset();
407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    USE(start);
408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ push_imm32(i);
409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch    __ jmp(&done);
410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch    DCHECK(masm()->pc_offset() - start == table_entry_size_);
411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  }
412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch  __ bind(&done);
413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}
414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FrameDescription::SetCallerPc(unsigned offset, intptr_t value) {
417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetFrameSlot(offset, value);
418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FrameDescription::SetCallerFp(unsigned offset, intptr_t value) {
422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  SetFrameSlot(offset, value);
423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) {
427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch  // No embedded constant pool support.
428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch  UNREACHABLE();
429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}
430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch
432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef __
433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch
435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace internal
436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}  // namespace v8
437b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch
438b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif  // V8_TARGET_ARCH_IA32
439