1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen 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_X87 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/register-configuration.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/safepoint-table.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/x87/frames-x87.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochconst int Deoptimizer::table_entry_size_ = 10; 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochint Deoptimizer::patch_size() { 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Assembler::kCallInstructionLength; 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Deoptimizer::EnsureRelocSpaceForLazyDeoptimization(Handle<Code> code) { 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = code->GetIsolate(); 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch HandleScope scope(isolate); 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute the size of relocation information needed for the code 30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // patching in Deoptimizer::PatchCodeForDeoptimization below. 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int min_reloc_size = 0; 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int prev_pc_offset = 0; 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizationInputData* deopt_data = 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizationInputData::cast(code->deoptimization_data()); 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < deopt_data->DeoptCount(); i++) { 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int pc_offset = deopt_data->Pc(i)->value(); 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (pc_offset == -1) continue; 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_GE(pc_offset, prev_pc_offset); 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int pc_delta = pc_offset - prev_pc_offset; 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We use RUNTIME_ENTRY reloc info which has a size of 2 bytes 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // if encodable with small pc delta encoding and up to 6 bytes 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // otherwise. 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (pc_delta <= RelocInfo::kMaxSmallPCDelta) { 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch min_reloc_size += 2; 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch min_reloc_size += 6; 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prev_pc_offset = pc_offset; 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the relocation information is not big enough we create a new 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // relocation info object that is padded with comments to make it 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // big enough for lazy doptimization. 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int reloc_length = code->relocation_info()->length(); 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (min_reloc_size > reloc_length) { 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int comment_reloc_size = RelocInfo::kMinRelocCommentSize; 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Padding needed. 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int min_padding = min_reloc_size - reloc_length; 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Number of comments needed to take up at least that much space. 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int additional_comments = 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (min_padding + comment_reloc_size - 1) / comment_reloc_size; 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Actual padding size. 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int padding = additional_comments * comment_reloc_size; 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate new relocation info and copy old relocation to the end 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // of the new relocation info array because relocation info is 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // written and read backwards. 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Factory* factory = isolate->factory(); 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<ByteArray> new_reloc = 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch factory->NewByteArray(reloc_length + padding, TENURED); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemCopy(new_reloc->GetDataStartAddress() + padding, 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->relocation_info()->GetDataStartAddress(), reloc_length); 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create a relocation writer to write the comments in the padding 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // space. Use position 0 for everything to ensure short encoding. 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfoWriter reloc_info_writer( 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch new_reloc->GetDataStartAddress() + padding, 0); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch intptr_t comment_string 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch = reinterpret_cast<intptr_t>(RelocInfo::kFillerCommentString); 78014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo rinfo(isolate, 0, RelocInfo::COMMENT, comment_string, NULL); 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < additional_comments; ++i) { 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch byte* pos_before = reloc_info_writer.pos(); 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reloc_info_writer.Write(&rinfo); 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(RelocInfo::kMinRelocCommentSize == 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch pos_before - reloc_info_writer.pos()); 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace relocation information on the code object. 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch code->set_relocation_info(*new_reloc); 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Deoptimizer::PatchCodeForDeoptimization(Isolate* isolate, Code* code) { 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address code_start_address = code->instruction_start(); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 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 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We will overwrite the code's relocation info in-place. Relocation info 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is written backward. The relocation info is the payload of a byte 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // array. Later on we will slide this to the start of the byte array and 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // create a filler object in the remaining space. 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ByteArray* reloc_info = code->relocation_info(); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address reloc_end_address = reloc_info->address() + reloc_info->Size(); 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfoWriter reloc_info_writer(reloc_end_address, code_start_address); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Since the call is a relative encoding, write new 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // reloc info. We do not need any of the existing reloc info because the 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // existing code will not be used again (we zap it in debug builds). 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Emit call to lazy deoptimization at all lazy deopt points. 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizationInputData* deopt_data = 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DeoptimizationInputData::cast(code->deoptimization_data()); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address prev_call_address = NULL; 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // For each LLazyBailout instruction insert a call to the corresponding 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // deoptimization entry. 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < deopt_data->DeoptCount(); i++) { 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (deopt_data->Pc(i)->value() == -1) continue; 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Patch lazy deoptimization entry. 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen 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); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We use RUNTIME_ENTRY for deoptimization bailouts. 145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RelocInfo rinfo(isolate, call_address + 1, // 1 after the call opcode. 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch RelocInfo::RUNTIME_ENTRY, 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch reinterpret_cast<intptr_t>(deopt_entry), NULL); 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reloc_info_writer.Write(&rinfo); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_GE(reloc_info_writer.pos(), 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch reloc_info->address() + ByteArray::kHeaderSize); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(prev_call_address == NULL || 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch call_address >= prev_call_address + patch_size()); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(call_address + patch_size() <= code->instruction_end()); 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#ifdef DEBUG 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch prev_call_address = call_address; 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 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 } 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Set the register values. The values are not important as there are no 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // callee saved registers in JavaScript frames, so all registers are 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // spilled. Registers ebp and esp are set to the correct values though. 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < Register::kNumRegisters; i++) { 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch input_->SetRegister(i, i * 4); 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); 182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (int i = 0; i < X87Register::kMaxNumRegisters; i++) { 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch input_->SetDoubleRegister(i, 0.0); 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fill the frame content from the actual data on the frame. 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen 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 < X87Register::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 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ masm()-> 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 228014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid Deoptimizer::TableEntryGenerator::Generate() { 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GeneratePrologue(); 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save all general purpose registers before messing with them. 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kNumberOfRegisters = Register::kNumRegisters; 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const int kDoubleRegsSize = kDoubleSize * X87Register::kMaxNumRegisters; 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Reserve space for x87 fp registers. 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kDoubleRegsSize)); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pushad(); 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 241014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference c_entry_fp_address(Isolate::kCEntryFPAddress, isolate()); 242014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(Operand::StaticVariable(c_entry_fp_address), ebp); 243014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // GP registers are safe to use now. 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Save used x87 fp registers in correct position of previous reserve space. 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop, done; 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the layout of x87 stack. 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(esp, Immediate(kPointerSize)); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fistp_s(MemOperand(esp, 0)); 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(eax); 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve stack layout in edi 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(edi, eax); 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the x87 stack depth, the first 3 bits. 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, eax); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(ecx, 0x7); 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &done, Label::kNear); 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop); 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shr(eax, 0x3); 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, eax); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(ebx, 0x7); // Extract the st_x index into ebx. 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Pop TOS to the correct position. The disp(0x20) is due to pushad. 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The st_i should be saved to (esp + ebx * kDoubleSize + 0x20). 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_d(Operand(esp, ebx, times_8, 0x20)); 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ dec(ecx); // Decrease stack depth. 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &loop, Label::kNear); 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kSavedRegistersAreaSize = 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kNumberOfRegisters * kPointerSize + kDoubleRegsSize; 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the bailout id from the stack. 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Operand(esp, kSavedRegistersAreaSize)); 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the address of the location in the code object 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and compute the fp-to-sp delta in register edx. 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, Operand(esp, kSavedRegistersAreaSize + 1 * kPointerSize)); 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(edx, Operand(esp, kSavedRegistersAreaSize + 2 * kPointerSize)); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(edx, ebp); 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ neg(edx); 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(edi); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allocate a new deoptimizer object. 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(6, eax); 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(ebp, JavaScriptFrameConstants::kFunctionOffset)); 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 0 * kPointerSize), eax); // Function. 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 1 * kPointerSize), Immediate(type())); // Bailout type. 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 2 * kPointerSize), ebx); // Bailout id. 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 3 * kPointerSize), ecx); // Code address or 0. 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 4 * kPointerSize), edx); // Fp-to-sp delta. 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 5 * kPointerSize), 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(ExternalReference::isolate_address(isolate()))); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllowExternalCallThatCantCauseGC scope(masm()); 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate()), 6); 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(edi); 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Preserve deoptimizer object in register eax and get the input 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // frame descriptor pointer. 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fill in the input registers. 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = kNumberOfRegisters - 1; i >= 0; i--) { 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = (i * kPointerSize) + FrameDescription::registers_offset(); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(Operand(ebx, offset)); 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int double_regs_offset = FrameDescription::double_registers_offset(); 312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch const RegisterConfiguration* config = 313014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch RegisterConfiguration::ArchDefault(RegisterConfiguration::CRANKSHAFT); 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fill in the double input registers. 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < X87Register::kMaxNumAllocatableRegisters; ++i) { 316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int code = config->GetAllocatableDoubleCode(i); 317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int dst_offset = code * kDoubleSize + double_regs_offset; 318014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int src_offset = code * kDoubleSize; 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(Operand(esp, src_offset)); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fstp_d(Operand(ebx, dst_offset)); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Clear FPU all exceptions. 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // TODO(ulan): Find out why the TOP register is not zero here in some cases, 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and check that the generated code never deoptimizes with unbalanced stack. 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fnclex(); 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Remove the bailout id, return address and the double registers. 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize)); 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute a pointer to the unwinding limit in register ecx; that is 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // the first stack slot not part of the input frame. 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(ecx, esp); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unwind the stack down to - but not including - the unwinding 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // limit and copy the contents of the activation frame to the input 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // frame description. 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset())); 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label pop_loop_header; 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&pop_loop_header); 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label pop_loop; 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&pop_loop); 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(Operand(edx, 0)); 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(edx, Immediate(sizeof(uint32_t))); 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&pop_loop_header); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ecx, esp); 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_equal, &pop_loop); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Compute the output frame in the deoptimizer. 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(edi); 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(eax); 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ PrepareCallCFunction(1, ebx); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(Operand(esp, 0 * kPointerSize), eax); 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch { 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllowExternalCallThatCantCauseGC scope(masm()); 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CallCFunction( 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::compute_output_frames_function(isolate()), 1); 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(eax); 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(edi); 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If frame was dynamically aligned, pop padding. 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label no_padding; 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Immediate(0)); 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(equal, &no_padding); 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ pop(ecx); 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_debug_code) { 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(ecx, Immediate(kAlignmentZapValue)); 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Assert(equal, kAlignmentMarkerExpected); 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&no_padding); 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Replace the current frame with the output frames. 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label outer_push_loop, inner_push_loop, 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch outer_loop_header, inner_loop_header; 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Outer loop state: eax = current FrameDescription**, edx = one past the 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // last FrameDescription**. 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, Operand(eax, Deoptimizer::output_offset())); 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(edx, Operand(eax, edx, times_4, 0)); 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&outer_loop_header); 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&outer_push_loop); 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Inner loop state: ebx = current FrameDescription*, ecx = loop index. 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ebx, Operand(eax, 0)); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&inner_loop_header); 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&inner_push_loop); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(ecx, Immediate(sizeof(uint32_t))); 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&inner_loop_header); 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ test(ecx, ecx); 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &inner_push_loop); 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(eax, Immediate(kPointerSize)); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&outer_loop_header); 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(eax, edx); 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(below, &outer_push_loop); 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In case of a failed STUB, we have to restore the x87 stack. 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // x87 stack layout is in edi. 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label loop2, done2; 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the x87 stack depth, the first 3 bits. 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(ecx, edi); 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(ecx, 0x7); 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(zero, &done2, Label::kNear); 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lea(ecx, Operand(ecx, ecx, times_2, 0)); 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&loop2); 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(eax, edi); 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ shr_cl(eax); 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ and_(eax, 0x7); 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ fld_d(Operand(ebx, eax, times_8, double_regs_offset)); 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sub(ecx, Immediate(0x3)); 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ j(not_zero, &loop2, Label::kNear); 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done2); 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push state, pc, and continuation from the last output frame. 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Operand(ebx, FrameDescription::state_offset())); 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Operand(ebx, FrameDescription::pc_offset())); 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Operand(ebx, FrameDescription::continuation_offset())); 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push the registers from the last output frame. 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < kNumberOfRegisters; i++) { 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int offset = (i * kPointerSize) + FrameDescription::registers_offset(); 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push(Operand(ebx, offset)); 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Restore the registers from the stack. 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ popad(); 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return to the continuation point. 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ret(0); 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid Deoptimizer::TableEntryGenerator::GeneratePrologue() { 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Create a sequence of deoptimization entries. 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < count(); i++) { 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int start = masm()->pc_offset(); 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch USE(start); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ push_imm32(i); 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&done); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(masm()->pc_offset() - start == table_entry_size_); 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FrameDescription::SetCallerPc(unsigned offset, intptr_t value) { 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetFrameSlot(offset, value); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FrameDescription::SetCallerFp(unsigned offset, intptr_t value) { 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch SetFrameSlot(offset, value); 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid FrameDescription::SetCallerConstantPool(unsigned offset, intptr_t value) { 464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // No embedded constant pool support. 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 472014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 473014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_X87 476