13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Redistribution and use in source and binary forms, with or without 3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// modification, are permitted provided that the following conditions are 4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// met: 5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Redistributions of source code must retain the above copyright 7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// notice, this list of conditions and the following disclaimer. 8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Redistributions in binary form must reproduce the above 9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// copyright notice, this list of conditions and the following 10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// disclaimer in the documentation and/or other materials provided 11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// with the distribution. 12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Neither the name of Google Inc. nor the names of its 13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// contributors may be used to endorse or promote products derived 14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from this software without specific prior written permission. 15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "v8.h" 29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "codegen.h" 31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h" 32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h" 33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "safepoint-table.h" 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 { 36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal { 37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochconst int Deoptimizer::table_entry_size_ = 16; 39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Deoptimizer::patch_size() { 421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int kCallInstructionSizeInWords = 3; 431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return kCallInstructionSizeInWords * Assembler::kInstrSize; 441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 47b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DeoptimizeFunction(JSFunction* function) { 4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope; 49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssertNoAllocation no_allocation; 50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!function->IsOptimized()) return; 52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the optimized code. 54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Code* code = function->code(); 552b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Address code_start_address = code->instruction_start(); 56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Invalidate the relocation information, as it will become invalid by the 58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // code patching below, and is not needed any more. 59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch code->InvalidateRelocation(); 60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 612b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // For each LLazyBailout instruction insert a call to the corresponding 622b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // deoptimization entry. 632b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch DeoptimizationInputData* deopt_data = 642b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch DeoptimizationInputData::cast(code->deoptimization_data()); 65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 662b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Address prev_call_address = NULL; 67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 682b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch for (int i = 0; i < deopt_data->DeoptCount(); i++) { 692b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch if (deopt_data->Pc(i)->value() == -1) continue; 702b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Address call_address = code_start_address + deopt_data->Pc(i)->value(); 712b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Address deopt_entry = GetDeoptimizationEntry(i, LAZY); 722b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch int call_size_in_bytes = MacroAssembler::CallSize(deopt_entry, 732b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch RelocInfo::NONE); 742b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch int call_size_in_words = call_size_in_bytes / Assembler::kInstrSize; 752b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(call_size_in_bytes % Assembler::kInstrSize == 0); 762b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(call_size_in_bytes <= patch_size()); 772b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch CodePatcher patcher(call_address, call_size_in_words); 782b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch patcher.masm()->Call(deopt_entry, RelocInfo::NONE); 792b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(prev_call_address == NULL || 802b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch call_address >= prev_call_address + patch_size()); 812b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(call_address + patch_size() <= code->instruction_end()); 82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 832b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch prev_call_address = call_address; 84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 852b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch } 86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate = code->GetIsolate(); 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Add the deoptimizing code to the list. 90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code); 913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizerData* data = isolate->deoptimizer_data(); 9244f0eee88ff00398ff7f715fab053374d808c90dSteve Block node->set_next(data->deoptimizing_code_list_); 9344f0eee88ff00398ff7f715fab053374d808c90dSteve Block data->deoptimizing_code_list_ = node; 94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We might be in the middle of incremental marking with compaction. 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tell collector to treat this code object in a special way and 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ignore all slots that might have been recorded on it. 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate->heap()->mark_compact_collector()->InvalidateCode(code); 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Set the code for the function to non-optimized version. 101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function->ReplaceCode(function->shared()->code()); 102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[forced deoptimization: "); 105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function->PrintName(); 106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" / %x]\n", reinterpret_cast<uint32_t>(function)); 107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int32_t kBranchBeforeStackCheck = 0x2a000001; 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic const int32_t kBranchBeforeInterrupt = 0x5a000004; 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code, 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address pc_after, 1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* check_code, 1181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* replacement_code) { 119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const int kInstrSize = Assembler::kInstrSize; 120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The call of the stack guard check has the following form: 121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // e1 5d 00 0c cmp sp, <limit> 122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // 2a 00 00 01 bcs ok 123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // e5 9f c? ?? ldr ip, [pc, <stack guard address>] 124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // e1 2f ff 3c blx ip 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(Memory::int32_at(pc_after - kInstrSize) == kBlxIp); 126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(Assembler::IsLdrPcImmediateOffset( 127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Assembler::instr_at(pc_after - 2 * kInstrSize))); 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_count_based_interrupts) { 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(kBranchBeforeInterrupt, 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Memory::int32_at(pc_after - 3 * kInstrSize)); 1313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(kBranchBeforeStackCheck, 1333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Memory::int32_at(pc_after - 3 * kInstrSize)); 1343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We patch the code to the following form: 137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // e1 5d 00 0c cmp sp, <limit> 138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // e1 a0 00 00 mov r0, r0 (NOP) 139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // e5 9f c? ?? ldr ip, [pc, <on-stack replacement address>] 140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // e1 2f ff 3c blx ip 141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // and overwrite the constant containing the 142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // address of the stack check stub. 143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Replace conditional jump with NOP. 145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CodePatcher patcher(pc_after - 3 * kInstrSize, 1); 146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch patcher.masm()->nop(); 147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Replace the stack check address in the constant pool 149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // with the entry address of the replacement code. 150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch uint32_t stack_check_address_offset = Memory::uint16_at(pc_after - 151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2 * kInstrSize) & 0xfff; 152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Address stack_check_address_pointer = pc_after + stack_check_address_offset; 153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(Memory::uint32_at(stack_check_address_pointer) == 154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch reinterpret_cast<uint32_t>(check_code->entry())); 155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Memory::uint32_at(stack_check_address_pointer) = 156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch reinterpret_cast<uint32_t>(replacement_code->entry()); 1573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 1593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unoptimized_code, pc_after - 2 * kInstrSize, replacement_code); 160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::RevertStackCheckCodeAt(Code* unoptimized_code, 1643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address pc_after, 1651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* check_code, 1661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* replacement_code) { 167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch const int kInstrSize = Assembler::kInstrSize; 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(Memory::int32_at(pc_after - kInstrSize) == kBlxIp); 1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(Assembler::IsLdrPcImmediateOffset( 1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Assembler::instr_at(pc_after - 2 * kInstrSize))); 171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Replace NOP with conditional jump. 173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CodePatcher patcher(pc_after - 3 * kInstrSize, 1); 1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_count_based_interrupts) { 1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch patcher.masm()->b(+16, pl); 1763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(kBranchBeforeInterrupt, 1773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Memory::int32_at(pc_after - 3 * kInstrSize)); 1783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch patcher.masm()->b(+4, cs); 1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(kBranchBeforeStackCheck, 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Memory::int32_at(pc_after - 3 * kInstrSize)); 1823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Replace the stack check address in the constant pool 185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // with the entry address of the replacement code. 186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch uint32_t stack_check_address_offset = Memory::uint16_at(pc_after - 187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2 * kInstrSize) & 0xfff; 188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Address stack_check_address_pointer = pc_after + stack_check_address_offset; 189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(Memory::uint32_at(stack_check_address_pointer) == 190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch reinterpret_cast<uint32_t>(replacement_code->entry())); 191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Memory::uint32_at(stack_check_address_pointer) = 192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch reinterpret_cast<uint32_t>(check_code->entry()); 1933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 1953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unoptimized_code, pc_after - 2 * kInstrSize, check_code); 196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockstatic int LookupBailoutId(DeoptimizationInputData* data, unsigned ast_id) { 2001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ByteArray* translations = data->TranslationByteArray(); 2011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int length = data->DeoptCount(); 2021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < length; i++) { 2031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (static_cast<unsigned>(data->AstId(i)->value()) == ast_id) { 2041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block TranslationIterator it(translations, data->TranslationIndex(i)->value()); 2051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int value = it.Next(); 2061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(Translation::BEGIN == static_cast<Translation::Opcode>(value)); 2071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Read the number of frames. 2081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = it.Next(); 2091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (value == 1) return i; 2101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 2131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return -1; 2141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 2151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DoComputeOsrOutputFrame() { 2181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizationInputData* data = DeoptimizationInputData::cast( 2191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block optimized_code_->deoptimization_data()); 2201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned ast_id = data->OsrAstId()->value(); 2211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int bailout_id = LookupBailoutId(data, ast_id); 2231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned translation_index = data->TranslationIndex(bailout_id)->value(); 2241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ByteArray* translations = data->TranslationByteArray(); 2251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block TranslationIterator iterator(translations, translation_index); 2271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Translation::Opcode opcode = 2281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block static_cast<Translation::Opcode>(iterator.Next()); 2291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(Translation::BEGIN == opcode); 2301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block USE(opcode); 2311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int count = iterator.Next(); 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch iterator.Skip(1); // Drop JS frame count. 2331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(count == 1); 2341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block USE(count); 2351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block opcode = static_cast<Translation::Opcode>(iterator.Next()); 2371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block USE(opcode); 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(Translation::JS_FRAME == opcode); 2391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned node_id = iterator.Next(); 2401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block USE(node_id); 2411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(node_id == ast_id); 2421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JSFunction* function = JSFunction::cast(ComputeLiteral(iterator.Next())); 2431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block USE(function); 2441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(function == function_); 2451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned height = iterator.Next(); 2461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned height_in_bytes = height * kPointerSize; 2471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block USE(height_in_bytes); 2481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned fixed_size = ComputeFixedSize(function_); 2501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned input_frame_size = input_->GetFrameSize(); 2511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(fixed_size + height_in_bytes == input_frame_size); 2521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; 2541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); 2551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned outgoing_size = outgoing_height * kPointerSize; 2561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; 2571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. 2581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_trace_osr) { 2601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", 2611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block reinterpret_cast<intptr_t>(function_)); 2621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block function_->PrintName(); 2631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" => node=%u, frame=%d->%d]\n", 2641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ast_id, 2651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block input_frame_size, 2661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame_size); 2671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // There's only one output frame in the OSR case. 2701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_count_ = 1; 2711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_ = new FrameDescription*[1]; 2721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_[0] = new(output_frame_size) FrameDescription( 2731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame_size, function_); 2743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT); 2751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Clear the incoming parameters in the optimized frame to avoid 2771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // confusing the garbage collector. 2781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned output_offset = output_frame_size - kPointerSize; 2791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int parameter_count = function_->shared()->formal_parameter_count() + 1; 2801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < parameter_count; ++i) { 2811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_[0]->SetFrameSlot(output_offset, 0); 2821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_offset -= kPointerSize; 2831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Translate the incoming parameters. This may overwrite some of the 2861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // incoming argument slots we've just cleared. 2871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int input_offset = input_frame_size - kPointerSize; 2881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool ok = true; 2891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int limit = input_offset - (parameter_count * kPointerSize); 2901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block while (ok && input_offset > limit) { 2911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ok = DoOsrTranslateCommand(&iterator, &input_offset); 2921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 2931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // There are no translation commands for the caller's pc and fp, the 2951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // context, and the function. Set them up explicitly. 29644f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = StandardFrameConstants::kCallerPCOffset; 29744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ok && i >= StandardFrameConstants::kMarkerOffset; 29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block i -= kPointerSize) { 2991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block uint32_t input_value = input_->GetFrameSlot(input_offset); 3001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_trace_osr) { 30144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const char* name = "UNKNOWN"; 30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block switch (i) { 30344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case StandardFrameConstants::kCallerPCOffset: 30444f0eee88ff00398ff7f715fab053374d808c90dSteve Block name = "caller's pc"; 30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case StandardFrameConstants::kCallerFPOffset: 30744f0eee88ff00398ff7f715fab053374d808c90dSteve Block name = "fp"; 30844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 30944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case StandardFrameConstants::kContextOffset: 31044f0eee88ff00398ff7f715fab053374d808c90dSteve Block name = "context"; 31144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 31244f0eee88ff00398ff7f715fab053374d808c90dSteve Block case StandardFrameConstants::kMarkerOffset: 31344f0eee88ff00398ff7f715fab053374d808c90dSteve Block name = "function"; 31444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 31544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 31644f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF(" [sp + %d] <- 0x%08x ; [sp + %d] (fixed part - %s)\n", 3171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_offset, 3181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block input_value, 31944f0eee88ff00398ff7f715fab053374d808c90dSteve Block input_offset, 32044f0eee88ff00398ff7f715fab053374d808c90dSteve Block name); 3211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 32244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset)); 3241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block input_offset -= kPointerSize; 3251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_offset -= kPointerSize; 3261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Translate the rest of the frame. 3291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block while (ok && input_offset >= 0) { 3301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ok = DoOsrTranslateCommand(&iterator, &input_offset); 3311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 3321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If translation of any command failed, continue using the input frame. 3341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!ok) { 3351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block delete output_[0]; 3361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_[0] = input_; 3371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); 3381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the frame pointer and the context pointer. 3401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_[0]->SetRegister(fp.code(), input_->GetRegister(fp.code())); 3411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_[0]->SetRegister(cp.code(), input_->GetRegister(cp.code())); 3421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned pc_offset = data->OsrPcOffset()->value(); 3441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block uint32_t pc = reinterpret_cast<uint32_t>( 3451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block optimized_code_->entry() + pc_offset); 3461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_[0]->SetPc(pc); 3471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Code* continuation = isolate_->builtins()->builtin(Builtins::kNotifyOSR); 3491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_[0]->SetContinuation( 3501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block reinterpret_cast<uint32_t>(continuation->entry())); 3511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_trace_osr) { 3531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", 3541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ok ? "finished" : "aborted", 3551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block reinterpret_cast<intptr_t>(function)); 3561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block function->PrintName(); 3571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" => pc=0x%0x]\n", output_[0]->GetPc()); 3581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int frame_index) { 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned height = iterator->Next(); 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned height_in_bytes = height * kPointerSize; 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes); 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned output_frame_size = height_in_bytes + fixed_frame_size; 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate and store the output frame description. 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameDescription* output_frame = 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(output_frame_size) FrameDescription(output_frame_size, function); 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR); 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Arguments adaptor can not be topmost or bottommost. 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(frame_index > 0 && frame_index < output_count_ - 1); 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(output_[frame_index] == NULL); 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_[frame_index] = output_frame; 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The top address of the frame is computed from the previous 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // frame's top and this frame's size. 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t top_address; 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetTop(top_address); 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the incoming parameter translation. 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int parameter_count = height; 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned output_offset = output_frame_size; 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < parameter_count; ++i) { 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoTranslateCommand(iterator, frame_index, output_offset); 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Read caller's PC from the previous frame. 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t callers_pc = output_[frame_index - 1]->GetPc(); 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, callers_pc); 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n", 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, callers_pc); 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Read caller's FP from the previous frame, and set this frame's FP. 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t value = output_[frame_index - 1]->GetFp(); 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t fp_value = top_address + output_offset; 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFp(fp_value); 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fp_value, output_offset, value); 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A marker value is used in place of the context. 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t context = reinterpret_cast<intptr_t>( 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, context); 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context (adaptor sentinel)\n", 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, context); 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME. 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = reinterpret_cast<intptr_t>(function); 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function\n", 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value); 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Number of incoming arguments. 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1)); 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n", 4433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value, height - 1); 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(0 == output_offset); 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Builtins* builtins = isolate_->builtins(); 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Code* adaptor_trampoline = 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t pc = reinterpret_cast<uint32_t>( 4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch adaptor_trampoline->instruction_start() + 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetPc(pc); 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int frame_index) { 4609413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch Builtins* builtins = isolate_->builtins(); 4619413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned height = iterator->Next(); 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned height_in_bytes = height * kPointerSize; 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" translating construct stub => height=%d\n", height_in_bytes); 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4699413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch unsigned fixed_frame_size = 8 * kPointerSize; 4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned output_frame_size = height_in_bytes + fixed_frame_size; 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate and store the output frame description. 4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameDescription* output_frame = 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(output_frame_size) FrameDescription(output_frame_size, function); 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameType(StackFrame::CONSTRUCT); 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Construct stub can not be topmost or bottommost. 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(frame_index > 0 && frame_index < output_count_ - 1); 4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(output_[frame_index] == NULL); 4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_[frame_index] = output_frame; 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The top address of the frame is computed from the previous 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // frame's top and this frame's size. 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t top_address; 4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetTop(top_address); 4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the incoming parameter translation. 4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int parameter_count = height; 4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned output_offset = output_frame_size; 4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < parameter_count; ++i) { 4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoTranslateCommand(iterator, frame_index, output_offset); 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Read caller's PC from the previous frame. 4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t callers_pc = output_[frame_index - 1]->GetPc(); 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, callers_pc); 5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n", 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, callers_pc); 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Read caller's FP from the previous frame, and set this frame's FP. 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t value = output_[frame_index - 1]->GetFp(); 5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t fp_value = top_address + output_offset; 5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFp(fp_value); 5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", 5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fp_value, output_offset, value); 5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The context can be gotten from the previous frame. 5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = output_[frame_index - 1]->GetContext(); 5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context\n", 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value); 5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A marker value is used in place of the function. 5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT)); 5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function (construct sentinel)\n", 5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value); 5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5349413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch // The output frame reflects a JSConstructStubGeneric frame. 5359413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch output_offset -= kPointerSize; 5369413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch value = reinterpret_cast<intptr_t>(construct_stub); 5379413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5389413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch if (FLAG_trace_deopt) { 5399413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; code object\n", 5409413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch top_address + output_offset, output_offset, value); 5419413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch } 5429413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch 5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Number of incoming arguments. 5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = reinterpret_cast<uint32_t>(Smi::FromInt(height - 1)); 5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; argc (%d)\n", 5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value, height - 1); 5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Constructor function being invoked by the stub. 5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = reinterpret_cast<intptr_t>(function); 5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; constructor function\n", 5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value); 5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The newly allocated object was passed as receiver in the artificial 5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // constructor stub environment created by HEnvironment::CopyForInlining(). 5633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); 5653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; allocated receiver\n", 5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value); 5693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(0 == output_offset); 5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t pc = reinterpret_cast<uint32_t>( 5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch construct_stub->instruction_start() + 5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate_->heap()->construct_stub_deopt_pc_offset()->value()); 5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetPc(pc); 5773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 5783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This code is very similar to ia32 code, but relies on register names (fp, sp) 581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// and how the frame is laid out. 5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, 5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int frame_index) { 584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Read the ast node id, function, and frame height for this output frame. 585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int node_id = iterator->Next(); 586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned height = iterator->Next(); 588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned height_in_bytes = height * kPointerSize; 589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" translating "); 591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function->PrintName(); 592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" => node=%d, height=%d\n", node_id, height_in_bytes); 593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The 'fixed' part of the frame consists of the incoming parameters and 596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the part described by JavaScriptFrameConstants. 597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned fixed_frame_size = ComputeFixedSize(function); 598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned input_frame_size = input_->GetFrameSize(); 599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned output_frame_size = height_in_bytes + fixed_frame_size; 600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Allocate and store the output frame description. 602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FrameDescription* output_frame = 603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new(output_frame_size) FrameDescription(output_frame_size, function); 6043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); 605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_bottommost = (0 == frame_index); 607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_topmost = (output_count_ - 1 == frame_index); 608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(frame_index >= 0 && frame_index < output_count_); 609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(output_[frame_index] == NULL); 610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index] = output_frame; 611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The top address for the bottommost output frame can be computed from 613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the input frame pointer and the output frame's height. For all 614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // subsequent output frames, it can be computed from the previous one's 615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // top address and the current frame's size. 616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t top_address; 617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_bottommost) { 618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // 2 = context and function in the frame. 619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch top_address = 620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_->GetRegister(fp.code()) - (2 * kPointerSize) - height_in_bytes; 621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetTop(top_address); 625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute the incoming parameter translation. 627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int parameter_count = function->shared()->formal_parameter_count() + 1; 628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned output_offset = output_frame_size; 629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned input_offset = input_frame_size; 630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < parameter_count; ++i) { 631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset -= kPointerSize; 632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoTranslateCommand(iterator, frame_index, output_offset); 633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_offset -= (parameter_count * kPointerSize); 635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There are no translation commands for the caller's pc and fp, the 637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // context, and the function. Synthesize their values and set them up 638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // explicitly. 639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // 640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The caller's pc for the bottommost output frame is the same as in the 641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // input frame. For all subsequent output frames, it can be read from the 642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // previous one. This frame's pc can be computed from the non-optimized 643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // function code and AST id of the bailout. 644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset -= kPointerSize; 645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_offset -= kPointerSize; 646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch intptr_t value; 647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_bottommost) { 648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = input_->GetFrameSlot(input_offset); 649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = output_[frame_index - 1]->GetPc(); 651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetFrameSlot(output_offset, value); 653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's pc\n", 655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch top_address + output_offset, output_offset, value); 656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The caller's frame pointer for the bottommost output frame is the same 659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // as in the input frame. For all subsequent output frames, it can be 660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // read from the previous one. Also compute and set this frame's frame 661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // pointer. 662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset -= kPointerSize; 663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_offset -= kPointerSize; 664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_bottommost) { 665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = input_->GetFrameSlot(input_offset); 666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = output_[frame_index - 1]->GetFp(); 668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetFrameSlot(output_offset, value); 670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch intptr_t fp_value = top_address + output_offset; 671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!is_bottommost || input_->GetRegister(fp.code()) == fp_value); 672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetFp(fp_value); 673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_topmost) { 674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetRegister(fp.code(), fp_value); 675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; caller's fp\n", 678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch fp_value, output_offset, value); 679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // For the bottommost output frame the context can be gotten from the input 682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // frame. For all subsequent output frames it can be gotten from the function 683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // so long as we don't inline functions that need local contexts. 684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset -= kPointerSize; 685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_offset -= kPointerSize; 686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (is_bottommost) { 687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch value = input_->GetFrameSlot(input_offset); 688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch value = reinterpret_cast<intptr_t>(function->context()); 690e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetFrameSlot(output_offset, value); 6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetContext(value); 6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_topmost) output_frame->SetRegister(cp.code(), value); 694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; context\n", 696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch top_address + output_offset, output_offset, value); 697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The function was mentioned explicitly in the BEGIN_FRAME. 700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset -= kPointerSize; 701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_offset -= kPointerSize; 702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = reinterpret_cast<uint32_t>(function); 703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The function for the bottommost output frame should also agree with the 704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // input frame. 705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value); 706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetFrameSlot(output_offset, value); 707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" 0x%08x: [top + %d] <- 0x%08x ; function\n", 709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch top_address + output_offset, output_offset, value); 710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Translate the rest of the frame. 713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (unsigned i = 0; i < height; ++i) { 714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset -= kPointerSize; 715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoTranslateCommand(iterator, frame_index, output_offset); 716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(0 == output_offset); 718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute this frame's PC, state, and continuation. 720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Code* non_optimized_code = function->shared()->code(); 721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FixedArray* raw_data = non_optimized_code->deoptimization_data(); 722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); 723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address start = non_optimized_code->instruction_start(); 724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); 725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); 726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t pc_value = reinterpret_cast<uint32_t>(start + pc_offset); 727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetPc(pc_value); 728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_topmost) { 729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetRegister(pc.code(), pc_value); 730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FullCodeGenerator::State state = 733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FullCodeGenerator::StateField::decode(pc_and_state); 734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetState(Smi::FromInt(state)); 735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 73644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Set the continuation for the topmost frame. 7383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_topmost && bailout_type_ != DEBUGGER) { 73944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Builtins* builtins = isolate_->builtins(); 740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Code* continuation = (bailout_type_ == EAGER) 74144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? builtins->builtin(Builtins::kNotifyDeoptimized) 74244f0eee88ff00398ff7f715fab053374d808c90dSteve Block : builtins->builtin(Builtins::kNotifyLazyDeoptimized); 743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_frame->SetContinuation( 744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reinterpret_cast<uint32_t>(continuation->entry())); 745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { 7503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Set the register values. The values are not important as there are no 7513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // callee saved registers in JavaScript frames, so all registers are 7523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // spilled. Registers fp and sp are set to the correct values though. 7533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < Register::kNumRegisters; i++) { 7553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch input_->SetRegister(i, i * 4); 7563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch input_->SetRegister(sp.code(), reinterpret_cast<intptr_t>(frame->sp())); 7583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch input_->SetRegister(fp.code(), reinterpret_cast<intptr_t>(frame->fp())); 7593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) { 7603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch input_->SetDoubleRegister(i, 0.0); 7613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Fill the frame content from the actual data on the frame. 7643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { 7653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); 7663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 7683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ masm()-> 771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This code tries to be close to ia32 code so that any changes can be 773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// easily ported. 774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::EntryGenerator::Generate() { 775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GeneratePrologue(); 77644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = masm()->isolate(); 77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CpuFeatures::Scope scope(VFP3); 780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Save all general purpose registers before messing with them. 781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const int kNumberOfRegisters = Register::kNumRegisters; 782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Everything but pc, lr and ip which will be saved but not restored. 784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RegList restored_regs = kJSCallerSaved | kCalleeSaved | ip.bit(); 785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const int kDoubleRegsSize = 787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch kDoubleSize * DwVfpRegister::kNumAllocatableRegisters; 788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Save all VFP registers before messing with them. 790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DwVfpRegister first = DwVfpRegister::FromAllocationIndex(0); 791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DwVfpRegister last = 792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DwVfpRegister::FromAllocationIndex( 793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DwVfpRegister::kNumAllocatableRegisters - 1); 794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(last.code() > first.code()); 795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT((last.code() - first.code()) == 796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (DwVfpRegister::kNumAllocatableRegisters - 1)); 797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG 798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i <= (DwVfpRegister::kNumAllocatableRegisters - 1); i++) { 799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT((DwVfpRegister::FromAllocationIndex(i).code() <= last.code()) && 800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (DwVfpRegister::FromAllocationIndex(i).code() >= first.code())); 801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ vstm(db_w, sp, first, last); 804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push all 16 registers (needed to populate FrameDescription::registers_). 80669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // TODO(1588) Note that using pc with stm is deprecated, so we should perhaps 80769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // handle this a bit differently. 808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ stm(db_w, sp, restored_regs | sp.bit() | lr.bit() | pc.bit()); 809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const int kSavedRegistersAreaSize = 811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (kNumberOfRegisters * kPointerSize) + kDoubleRegsSize; 812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the bailout id from the stack. 814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r2, MemOperand(sp, kSavedRegistersAreaSize)); 815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the address of the location in the code object if possible (r3) (return 817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // address for lazy deoptimization) and compute the fp-to-sp delta in 818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // register r4. 819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (type() == EAGER) { 820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(r3, Operand(0)); 821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Correct one word for bailout id. 822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(r4, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); 8231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (type() == OSR) { 8241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ mov(r3, lr); 8251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Correct one word for bailout id. 8261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ add(r4, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); 827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(r3, lr); 829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Correct two words for bailout id and return address. 830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(r4, sp, Operand(kSavedRegistersAreaSize + (2 * kPointerSize))); 831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sub(r4, fp, r4); 833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Allocate a new deoptimizer object. 835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Pass four arguments in r0 to r3 and fifth argument on stack. 8368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ PrepareCallCFunction(6, r5); 837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); 838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(r1, Operand(type())); // bailout type, 839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // r2: bailout id already loaded. 840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // r3: code address or 0 already loaded. 841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ str(r4, MemOperand(sp, 0 * kPointerSize)); // Fp-to-sp delta. 8428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ mov(r5, Operand(ExternalReference::isolate_address())); 8438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ str(r5, MemOperand(sp, 1 * kPointerSize)); // Isolate. 844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Call Deoptimizer::New(). 8453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 8463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm()); 8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6); 8483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Preserve "deoptimizer" object in register r0 and get the input 851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // frame descriptor pointer to r1 (deoptimizer->input_); 852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r1, MemOperand(r0, Deoptimizer::input_offset())); 853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Copy core registers into FrameDescription::registers_[kNumRegisters]. 855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(Register::kNumRegisters == kNumberOfRegisters); 856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < kNumberOfRegisters; i++) { 8571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = (i * kPointerSize) + FrameDescription::registers_offset(); 858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r2, MemOperand(sp, i * kPointerSize)); 859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ str(r2, MemOperand(r1, offset)); 860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Copy VFP registers to 863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // double_registers_[DoubleRegister::kNumAllocatableRegisters] 864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int double_regs_offset = FrameDescription::double_registers_offset(); 865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < DwVfpRegister::kNumAllocatableRegisters; ++i) { 866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int dst_offset = i * kDoubleSize + double_regs_offset; 867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int src_offset = i * kDoubleSize + kNumberOfRegisters * kPointerSize; 868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ vldr(d0, sp, src_offset); 869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ vstr(d0, r1, dst_offset); 870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Remove the bailout id, eventually return address, and the saved registers 873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // from the stack. 8741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (type() == EAGER || type() == OSR) { 875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(sp, sp, Operand(kSavedRegistersAreaSize + (1 * kPointerSize))); 876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(sp, sp, Operand(kSavedRegistersAreaSize + (2 * kPointerSize))); 878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute a pointer to the unwinding limit in register r2; that is 881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the first stack slot not part of the input frame. 882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r2, MemOperand(r1, FrameDescription::frame_size_offset())); 883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(r2, r2, sp); 884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Unwind the stack down to - but not including - the unwinding 886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // limit and copy the contents of the activation frame to the input 887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // frame description. 888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(r3, r1, Operand(FrameDescription::frame_content_offset())); 889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label pop_loop; 890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&pop_loop); 891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(r4); 892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ str(r4, MemOperand(r3, 0)); 893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(r3, r3, Operand(sizeof(uint32_t))); 894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r2, sp); 895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(ne, &pop_loop); 896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute the output frame in the deoptimizer. 898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(r0); // Preserve deoptimizer object across call. 899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // r0: deoptimizer object; r1: scratch. 900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ PrepareCallCFunction(1, r1); 901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Call Deoptimizer::ComputeOutputFrames(). 9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm()); 9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::compute_output_frames_function(isolate), 1); 9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(r0); // Restore deoptimizer object (class Deoptimizer). 908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Replace the current (input) frame with the output frames. 910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label outer_push_loop, inner_push_loop; 911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Outer loop state: r0 = current "FrameDescription** output_", 912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // r1 = one past the last FrameDescription**. 913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r1, MemOperand(r0, Deoptimizer::output_count_offset())); 914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r0, MemOperand(r0, Deoptimizer::output_offset())); // r0 is output_. 915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(r1, r0, Operand(r1, LSL, 2)); 916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&outer_push_loop); 917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Inner loop state: r2 = current FrameDescription*, r3 = loop index. 918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r2, MemOperand(r0, 0)); // output_[ix] 919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r3, MemOperand(r2, FrameDescription::frame_size_offset())); 920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&inner_push_loop); 921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ sub(r3, r3, Operand(sizeof(uint32_t))); 922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(r6, r2, Operand(r3)); 923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r7, MemOperand(r6, FrameDescription::frame_content_offset())); 924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(r7); 925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r3, Operand(0)); 926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(ne, &inner_push_loop); // test for gt? 927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ add(r0, r0, Operand(kPointerSize)); 928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ cmp(r0, r1); 929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(lt, &outer_push_loop); 930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push state, pc, and continuation from the last output frame. 932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (type() != OSR) { 933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r6, MemOperand(r2, FrameDescription::state_offset())); 934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(r6); 935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r6, MemOperand(r2, FrameDescription::pc_offset())); 938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(r6); 939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r6, MemOperand(r2, FrameDescription::continuation_offset())); 940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(r6); 941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push the registers from the last output frame. 943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = kNumberOfRegisters - 1; i >= 0; i--) { 9441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = (i * kPointerSize) + FrameDescription::registers_offset(); 945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldr(r6, MemOperand(r2, offset)); 946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(r6); 947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Restore the registers from the stack. 950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ ldm(ia_w, sp, restored_regs); // all but pc registers. 951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(ip); // remove sp 952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(ip); // remove lr 953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 954c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch __ InitializeRootRegister(); 955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(ip); // remove pc 957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(r7); // get continuation, leave pc on stack 958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ pop(lr); 959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ Jump(r7); 960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ stop("Unreachable."); 961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::TableEntryGenerator::GeneratePrologue() { 965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Create a sequence of deoptimization entries. Note that any 966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // registers may be still live. 967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label done; 968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < count(); i++) { 969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int start = masm()->pc_offset(); 970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch USE(start); 971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (type() == EAGER) { 972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ nop(); 973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Emulate ia32 like call by pushing return address to stack. 975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(lr); 976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ mov(ip, Operand(i)); 978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ push(ip); 979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ b(&done); 980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(masm()->pc_offset() - start == table_entry_size_); 981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&done); 983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef __ 986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} } // namespace v8::internal 988