1659ceec4628056d3c6e7076c850fba1c412cbb8ayangguo@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
23484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// Use of this source code is governed by a BSD-style license that can be
33484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org// found in the LICENSE file.
4a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
5196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
6a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
793a47f4837f2137c8d8349250fd8e91da3108126jkummerow@chromium.org#if V8_TARGET_ARCH_IA32
8c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org
9196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/codegen.h"
10196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/deoptimizer.h"
11196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/full-codegen.h"
12196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/safepoint-table.h"
13a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
14a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgnamespace v8 {
15a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgnamespace internal {
16a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
177c2628c3f0353f0558760c3ca442f934263ea766kmillikin@chromium.orgconst int Deoptimizer::table_entry_size_ = 10;
18a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
1931b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
2031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.orgint Deoptimizer::patch_size() {
2131b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  return Assembler::kCallInstructionLength;
2231b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org}
2331b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
2431b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
257979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.orgvoid Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) {
267979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  Isolate* isolate = code->GetIsolate();
277979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  HandleScope scope(isolate);
287979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
297979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // Compute the size of relocation information needed for the code
307979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // patching in Deoptimizer::DeoptimizeFunction.
317979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  int min_reloc_size = 0;
3227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  int prev_pc_offset = 0;
3327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  DeoptimizationInputData* deopt_data =
3427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      DeoptimizationInputData::cast(code->deoptimization_data());
3527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
3627bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    int pc_offset = deopt_data->Pc(i)->value();
3727bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    if (pc_offset == -1) continue;
38e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_GE(pc_offset, prev_pc_offset);
3927bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    int pc_delta = pc_offset - prev_pc_offset;
4027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // We use RUNTIME_ENTRY reloc info which has a size of 2 bytes
4127bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // if encodable with small pc delta encoding and up to 6 bytes
4227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // otherwise.
4327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    if (pc_delta <= RelocInfo::kMaxSmallPCDelta) {
4427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      min_reloc_size += 2;
4527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    } else {
4627bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      min_reloc_size += 6;
477979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    }
4827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    prev_pc_offset = pc_offset;
497979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  }
507979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
517979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // If the relocation information is not big enough we create a new
527979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // relocation info object that is padded with comments to make it
537979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  // big enough for lazy doptimization.
547979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  int reloc_length = code->relocation_info()->length();
557979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  if (min_reloc_size > reloc_length) {
567979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    int comment_reloc_size = RelocInfo::kMinRelocCommentSize;
577979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    // Padding needed.
587979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    int min_padding = min_reloc_size - reloc_length;
597979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    // Number of comments needed to take up at least that much space.
607979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    int additional_comments =
617979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org        (min_padding + comment_reloc_size - 1) / comment_reloc_size;
627979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    // Actual padding size.
637979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    int padding = additional_comments * comment_reloc_size;
647979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    // Allocate new relocation info and copy old relocation to the end
657979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    // of the new relocation info array because relocation info is
667979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    // written and read backwards.
677979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    Factory* factory = isolate->factory();
687979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    Handle<ByteArray> new_reloc =
697979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org        factory->NewByteArray(reloc_length + padding, TENURED);
70d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org    MemCopy(new_reloc->GetDataStartAddress() + padding,
71d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org            code->relocation_info()->GetDataStartAddress(), reloc_length);
727979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    // Create a relocation writer to write the comments in the padding
737979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    // space. Use position 0 for everything to ensure short encoding.
747979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    RelocInfoWriter reloc_info_writer(
757979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org        new_reloc->GetDataStartAddress() + padding, 0);
767979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    intptr_t comment_string
777979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org        = reinterpret_cast<intptr_t>(RelocInfo::kFillerCommentString);
78c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    RelocInfo rinfo(0, RelocInfo::COMMENT, comment_string, NULL);
797979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    for (int i = 0; i < additional_comments; ++i) {
807979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org#ifdef DEBUG
817979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      byte* pos_before = reloc_info_writer.pos();
827979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org#endif
837979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org      reloc_info_writer.Write(&rinfo);
84e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org      DCHECK(RelocInfo::kMinRelocCommentSize ==
857979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org             pos_before - reloc_info_writer.pos());
867979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    }
877979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    // Replace relocation information on the code object.
887979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org    code->set_relocation_info(*new_reloc);
897979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  }
907979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org}
917979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org
92a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
93fb732b17922ea75830be4db6b80534c4827d8a55jkummerow@chromium.orgvoid Deoptimizer::PatchCodeForDeoptimization(Isolate* isolate, Code* code) {
9483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  Address code_start_address = code->instruction_start();
95f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
96f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  if (FLAG_zap_code_space) {
97f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    // Fail hard and early if we enter this code object again.
98f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    byte* pointer = code->FindCodeAgeSequence();
99f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (pointer != NULL) {
100f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      pointer += kNoCodeAgeSequenceLength;
101f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    } else {
102f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      pointer = code->instruction_start();
103f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
104f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    CodePatcher patcher(pointer, 1);
105f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    patcher.masm()->int3();
106f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
107f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    DeoptimizationInputData* data =
108f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org        DeoptimizationInputData::cast(code->deoptimization_data());
109f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    int osr_offset = data->OsrPcOffset()->value();
110f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    if (osr_offset > 0) {
111f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      CodePatcher osr_patcher(code->instruction_start() + osr_offset, 1);
112f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org      osr_patcher.masm()->int3();
113f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org    }
114f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  }
115f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org
11631b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  // We will overwrite the code's relocation info in-place. Relocation info
11783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // is written backward. The relocation info is the payload of a byte
11883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // array.  Later on we will slide this to the start of the byte array and
11983aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // create a filler object in the remaining space.
12031b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  ByteArray* reloc_info = code->relocation_info();
12183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  Address reloc_end_address = reloc_info->address() + reloc_info->Size();
12283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  RelocInfoWriter reloc_info_writer(reloc_end_address, code_start_address);
12383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org
12427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  // Since the call is a relative encoding, write new
12583aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // reloc info.  We do not need any of the existing reloc info because the
12683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  // existing code will not be used again (we zap it in debug builds).
12727bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  //
12827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  // Emit call to lazy deoptimization at all lazy deopt points.
12927bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  DeoptimizationInputData* deopt_data =
13027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org      DeoptimizationInputData::cast(code->deoptimization_data());
13127bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org#ifdef DEBUG
13227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  Address prev_call_address = NULL;
13327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org#endif
134f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // For each LLazyBailout instruction insert a call to the corresponding
135f5a24546072ecdbbd6372c85c42157e01e913561titzer@chromium.org  // deoptimization entry.
13627bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org  for (int i = 0; i < deopt_data->DeoptCount(); i++) {
13727bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    if (deopt_data->Pc(i)->value() == -1) continue;
13827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // Patch lazy deoptimization entry.
13927bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    Address call_address = code_start_address + deopt_data->Pc(i)->value();
14027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    CodePatcher patcher(call_address, patch_size());
1418432c9102e4b2125d8eec741d35237cf23167471hpayer@chromium.org    Address deopt_entry = GetDeoptimizationEntry(isolate, i, LAZY);
14259297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org    patcher.masm()->call(deopt_entry, RelocInfo::NONE32);
14327bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    // We use RUNTIME_ENTRY for deoptimization bailouts.
14427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    RelocInfo rinfo(call_address + 1,  // 1 after the call opcode.
14527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org                    RelocInfo::RUNTIME_ENTRY,
14627bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org                    reinterpret_cast<intptr_t>(deopt_entry),
14727bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org                    NULL);
14827bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    reloc_info_writer.Write(&rinfo);
149e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK_GE(reloc_info_writer.pos(),
15027bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org              reloc_info->address() + ByteArray::kHeaderSize);
151e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(prev_call_address == NULL ||
15227bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org           call_address >= prev_call_address + patch_size());
153e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(call_address + patch_size() <= code->instruction_end());
15427bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org#ifdef DEBUG
15527bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org    prev_call_address = call_address;
15627bf28851c1fa362a3f7c709871c21dcc9c23ce7ricow@chromium.org#endif
157a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
158a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
15931b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  // Move the relocation info to the beginning of the byte array.
16083aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  int new_reloc_size = reloc_end_address - reloc_info_writer.pos();
161d06b9264b1c886fc80a100e9915cf8ae07fdb4e5machenbach@chromium.org  MemMove(code->relocation_start(), reloc_info_writer.pos(), new_reloc_size);
16231b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
16331b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  // The relocation info is in place, update the size.
16483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  reloc_info->set_length(new_reloc_size);
16531b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org
16631b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  // Handle the junk part after the new relocation info. We will create
16731b1277ec3b8cd17acb01c66d85a456159072157kmillikin@chromium.org  // a non-live object in the extra space at the end of the former reloc info.
16883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org  Address junk_address = reloc_info->address() + reloc_info->Size();
169e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(junk_address <= reloc_end_address);
1707979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org  isolate->heap()->CreateFillerObjectAt(junk_address,
1717979bbb1df2eaff193e85d44c8da1ffa1525b7fcfschneider@chromium.org                                        reloc_end_address - junk_address);
172a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
173a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
174a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
1754f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.orgvoid Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) {
1764f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Set the register values. The values are not important as there are no
1774f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // callee saved registers in JavaScript frames, so all registers are
1784f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // spilled. Registers ebp and esp are set to the correct values though.
1794f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
1804f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  for (int i = 0; i < Register::kNumRegisters; i++) {
1814f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    input_->SetRegister(i, i * 4);
1824f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
1834f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp()));
1844f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp()));
1851e4822ffed805d9cbb2a47cc9453aef06f3dfacamachenbach@chromium.org  for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; i++) {
1864f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    input_->SetDoubleRegister(i, 0.0);
1874f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
1884f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
1894f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  // Fill the frame content from the actual data on the frame.
1904f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) {
1914f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org    input_->SetFrameSlot(i, Memory::uint32_at(tos + i));
1924f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org  }
1934f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org}
1944f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
1954f693d6b99ffdbc05e5e211e08ed5039e13279d2ricow@chromium.org
1966e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.orgvoid Deoptimizer::SetPlatformCompiledStubRegisters(
197e20e19efeef112c26d0e63b1e5118e695b42d855machenbach@chromium.org    FrameDescription* output_frame, CodeStubDescriptor* descriptor) {
1986e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  intptr_t handler =
19947390597afd6b17870f41dfb5dd8c057aea1f068machenbach@chromium.org      reinterpret_cast<intptr_t>(descriptor->deoptimization_handler());
2000cc095007a3ccded63f6577751c6a04300eb7ae9machenbach@chromium.org  int params = descriptor->GetHandlerParameterCount();
2016e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  output_frame->SetRegister(eax.code(), params);
2026e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  output_frame->SetRegister(ebx.code(), handler);
2036e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org}
2046e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
2056e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
2066e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.orgvoid Deoptimizer::CopyDoubleRegisters(FrameDescription* output_frame) {
2071e4822ffed805d9cbb2a47cc9453aef06f3dfacamachenbach@chromium.org  for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
2086e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org    double double_value = input_->GetDoubleRegister(i);
2096e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org    output_frame->SetDoubleRegister(i, double_value);
2106e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org  }
2116e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org}
2126e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
2136e196bfaf0e555d0c835390bb6ebc0a74484491dulan@chromium.org
2144e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.orgbool Deoptimizer::HasAlignmentPadding(JSFunction* function) {
2154e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  int parameter_count = function->shared()->formal_parameter_count() + 1;
2164e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  unsigned input_frame_size = input_->GetFrameSize();
2174e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  unsigned alignment_state_offset =
2184e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      input_frame_size - parameter_count * kPointerSize -
2194e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      StandardFrameConstants::kFixedFrameSize -
2204e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      kPointerSize;
221e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org  DCHECK(JavaScriptFrameConstants::kDynamicAlignmentStateOffset ==
2224e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org      JavaScriptFrameConstants::kLocal0Offset);
2234e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  int32_t alignment_state = input_->GetFrameSlot(alignment_state_offset);
2244e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org  return (alignment_state == kAlignmentPaddingPushed);
2254e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org}
2264e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
2274e308cf00936c6e7bead43e5141a04e37b49b9b5jkummerow@chromium.org
228a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#define __ masm()->
229a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
230a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Deoptimizer::EntryGenerator::Generate() {
231a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  GeneratePrologue();
232a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
233a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Save all general purpose registers before messing with them.
234a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  const int kNumberOfRegisters = Register::kNumRegisters;
235a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
236a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  const int kDoubleRegsSize = kDoubleSize *
2371e4822ffed805d9cbb2a47cc9453aef06f3dfacamachenbach@chromium.org                              XMMRegister::kMaxNumAllocatableRegisters;
238c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(esp, Immediate(kDoubleRegsSize));
2391e4822ffed805d9cbb2a47cc9453aef06f3dfacamachenbach@chromium.org  for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
2403c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
2413c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    int offset = i * kDoubleSize;
2423c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movsd(Operand(esp, offset), xmm_reg);
243a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
244a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
245a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ pushad();
246a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
247a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize +
248a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org                                      kDoubleRegsSize;
249a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
250a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Get the bailout id from the stack.
251a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(ebx, Operand(esp, kSavedRegistersAreaSize));
252a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
253169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Get the address of the location in the code object
254a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // and compute the fp-to-sp delta in register edx.
255169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ mov(ecx, Operand(esp, kSavedRegistersAreaSize + 1 * kPointerSize));
256169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ lea(edx, Operand(esp, kSavedRegistersAreaSize + 2 * kPointerSize));
257169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org
258c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(edx, ebp);
259a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ neg(edx);
260a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
261a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Allocate a new deoptimizer object.
262c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ PrepareCallCFunction(6, eax);
263a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset));
264a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(Operand(esp, 0 * kPointerSize), eax);  // Function.
265a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(Operand(esp, 1 * kPointerSize), Immediate(type()));  // Bailout type.
266a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(Operand(esp, 2 * kPointerSize), ebx);  // Bailout id.
267a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(Operand(esp, 3 * kPointerSize), ecx);  // Code address or 0.
268a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(Operand(esp, 4 * kPointerSize), edx);  // Fp-to-sp delta.
269c36ce6e8979bbbd43539f0a0effc87ea20dd65cckmillikin@chromium.org  __ mov(Operand(esp, 5 * kPointerSize),
27032d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org         Immediate(ExternalReference::isolate_address(isolate())));
271c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
272c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    AllowExternalCallThatCantCauseGC scope(masm());
27332d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org    __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate()), 6);
274c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
275a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
276a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Preserve deoptimizer object in register eax and get the input
277a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // frame descriptor pointer.
278a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(ebx, Operand(eax, Deoptimizer::input_offset()));
279a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
280a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Fill in the input registers.
2810ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org  for (int i = kNumberOfRegisters - 1; i >= 0; i--) {
2820ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    int offset = (i * kPointerSize) + FrameDescription::registers_offset();
2830ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    __ pop(Operand(ebx, offset));
284a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
285a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
286a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  int double_regs_offset = FrameDescription::double_registers_offset();
2873c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org  // Fill in the double input registers.
2881e4822ffed805d9cbb2a47cc9453aef06f3dfacamachenbach@chromium.org  for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
2893c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    int dst_offset = i * kDoubleSize + double_regs_offset;
2903c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    int src_offset = i * kDoubleSize;
2913c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movsd(xmm0, Operand(esp, src_offset));
2923c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movsd(Operand(ebx, dst_offset), xmm0);
293a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
29446a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
295c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org  // Clear FPU all exceptions.
296c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org  // TODO(ulan): Find out why the TOP register is not zero here in some cases,
297c03a1924dcc113678c0ebe58aa7d3c855a657719yangguo@chromium.org  // and check that the generated code never deoptimizes with unbalanced stack.
29846a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  __ fnclex();
299a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
300169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  // Remove the bailout id, return address and the double registers.
301169691d93a961c8b511f8ac8fd8ee33d081ca10fdanno@chromium.org  __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize));
302a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
303a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Compute a pointer to the unwinding limit in register ecx; that is
304a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // the first stack slot not part of the input frame.
305a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset()));
306c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(ecx, esp);
307a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
308a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Unwind the stack down to - but not including - the unwinding
309a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // limit and copy the contents of the activation frame to the input
310a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // frame description.
311a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset()));
312a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Label pop_loop_header;
313a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ jmp(&pop_loop_header);
314a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label pop_loop;
315a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&pop_loop);
316a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ pop(Operand(edx, 0));
317c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(edx, Immediate(sizeof(uint32_t)));
318a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ bind(&pop_loop_header);
319c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(ecx, esp);
320a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ j(not_equal, &pop_loop);
321a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
322a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Compute the output frame in the deoptimizer.
323a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ push(eax);
324a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ PrepareCallCFunction(1, ebx);
325a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(Operand(esp, 0 * kPointerSize), eax);
326c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  {
327c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    AllowExternalCallThatCantCauseGC scope(masm());
328c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com    __ CallCFunction(
32932d7dbafe29be06cec1edd36c31fbe2865c799f4ulan@chromium.org        ExternalReference::compute_output_frames_function(isolate()), 1);
330c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  }
331a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ pop(eax);
332a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
333c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // If frame was dynamically aligned, pop padding.
334c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  Label no_padding;
335c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()),
336c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org         Immediate(0));
337c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ j(equal, &no_padding);
338c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ pop(ecx);
339c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  if (FLAG_debug_code) {
340c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    __ cmp(ecx, Immediate(kAlignmentZapValue));
341c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org    __ Assert(equal, kAlignmentMarkerExpected);
3427028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org  }
343c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ bind(&no_padding);
3447028c05c1c71b9d5c5fe1bca01f2461d17a2dda7mmassi@chromium.org
345a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Replace the current frame with the output frames.
346a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Label outer_push_loop, inner_push_loop,
347a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      outer_loop_header, inner_loop_header;
348a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Outer loop state: eax = current FrameDescription**, edx = one past the
349a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // last FrameDescription**.
350a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(edx, Operand(eax, Deoptimizer::output_count_offset()));
351a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(eax, Operand(eax, Deoptimizer::output_offset()));
352a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ lea(edx, Operand(eax, edx, times_4, 0));
353a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ jmp(&outer_loop_header);
354a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&outer_push_loop);
355a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Inner loop state: ebx = current FrameDescription*, ecx = loop index.
356a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(ebx, Operand(eax, 0));
357a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset()));
358a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ jmp(&inner_loop_header);
359a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&inner_push_loop);
360c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ sub(ecx, Immediate(sizeof(uint32_t)));
361a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset()));
362a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ bind(&inner_loop_header);
363c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ test(ecx, ecx);
364a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ j(not_zero, &inner_push_loop);
365c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ add(eax, Immediate(kPointerSize));
366a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  __ bind(&outer_loop_header);
367c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  __ cmp(eax, edx);
368a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ j(below, &outer_push_loop);
369a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
370c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // In case of a failed STUB, we have to restore the XMM registers.
3711e4822ffed805d9cbb2a47cc9453aef06f3dfacamachenbach@chromium.org  for (int i = 0; i < XMMRegister::kMaxNumAllocatableRegisters; ++i) {
3723c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i);
3733c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    int src_offset = i * kDoubleSize + double_regs_offset;
3743c3c8d733702cb2b41471efa5eead1faf5b5711bmachenbach@chromium.org    __ movsd(xmm_reg, Operand(ebx, src_offset));
375a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
376a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
377a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Push state, pc, and continuation from the last output frame.
378c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  __ push(Operand(ebx, FrameDescription::state_offset()));
379a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ push(Operand(ebx, FrameDescription::pc_offset()));
380a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ push(Operand(ebx, FrameDescription::continuation_offset()));
381a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
382a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
383a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Push the registers from the last output frame.
384a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  for (int i = 0; i < kNumberOfRegisters; i++) {
3850ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org    int offset = (i * kPointerSize) + FrameDescription::registers_offset();
386a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ push(Operand(ebx, offset));
387a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
388a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
389a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Restore the registers from the stack.
390a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ popad();
391a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
392a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Return to the continuation point.
393a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ ret(0);
394a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
395a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
396a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
397a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.orgvoid Deoptimizer::TableEntryGenerator::GeneratePrologue() {
398a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  // Create a sequence of deoptimization entries.
399a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  Label done;
400a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  for (int i = 0; i < count(); i++) {
401a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    int start = masm()->pc_offset();
402a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    USE(start);
403a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ push_imm32(i);
404a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org    __ jmp(&done);
405e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(masm()->pc_offset() - start == table_entry_size_);
406a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  }
407a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org  __ bind(&done);
408a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org}
409a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
410c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
411c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgvoid FrameDescription::SetCallerPc(unsigned offset, intptr_t value) {
412c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  SetFrameSlot(offset, value);
413c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org}
414c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
415c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
416c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.orgvoid FrameDescription::SetCallerFp(unsigned offset, intptr_t value) {
417c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org  SetFrameSlot(offset, value);
418c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org}
419c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
420c73d55b355913690124f3ee70c344035431cdd3ayangguo@chromium.org
4216b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.orgvoid FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) {
4226b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  // No out-of-line constant pool support.
4236b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org  UNREACHABLE();
4246b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org}
4256b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
4266b6df382019a622ba20133e47bbe2e6f323b013bdslomov@chromium.org
427a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#undef __
428a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
429a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
430a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} }  // namespace v8::internal
431c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org
432c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org#endif  // V8_TARGET_ARCH_IA32
433