13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 281362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// Redistribution and use in source and binary forms, with or without 381362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// modification, are permitted provided that the following conditions are 481362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// met: 581362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// 681362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// * Redistributions of source code must retain the above copyright 781362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// notice, this list of conditions and the following disclaimer. 881362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// * Redistributions in binary form must reproduce the above 981362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// copyright notice, this list of conditions and the following 1081362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// disclaimer in the documentation and/or other materials provided 1181362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// with the distribution. 1281362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// * Neither the name of Google Inc. nor the names of its 1381362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// contributors may be used to endorse or promote products derived 1481362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// from this software without specific prior written permission. 1581362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// 1681362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1781362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1881362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1981362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2081362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2181362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2281362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2381362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2481362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2581362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2681362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2781362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen 28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "v8.h" 2981362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen 30b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#if defined(V8_TARGET_ARCH_X64) 31b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "codegen.h" 33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "deoptimizer.h" 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h" 35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "safepoint-table.h" 3681362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen 37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 { 38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal { 3981362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen 40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochconst int Deoptimizer::table_entry_size_ = 10; 42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockint Deoptimizer::patch_size() { 452b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch return Assembler::kCallInstructionLength; 4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DeoptimizeFunction(JSFunction* function) { 5044f0eee88ff00398ff7f715fab053374d808c90dSteve Block HandleScope scope; 511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AssertNoAllocation no_allocation; 521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!function->IsOptimized()) return; 541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Get the optimized code. 561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* code = function->code(); 571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Invalidate the relocation information, as it will become invalid by the 591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // code patching below, and is not needed any more. 601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block code->InvalidateRelocation(); 611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 622b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // For each LLazyBailout instruction insert a absolute call to the 631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // corresponding deoptimization entry, or a short call to an absolute 641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // jump if space is short. The absolute jumps are put in a table just 651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // before the safepoint table (space was allocated there when the Code 661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // object was created, if necessary). 671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Address instruction_start = function->code()->instruction_start(); 691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef DEBUG 702b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Address prev_call_address = NULL; 711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 722b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch DeoptimizationInputData* deopt_data = 732b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch DeoptimizationInputData::cast(code->deoptimization_data()); 742b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch for (int i = 0; i < deopt_data->DeoptCount(); i++) { 752b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch if (deopt_data->Pc(i)->value() == -1) continue; 761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Position where Call will be patched in. 772b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch Address call_address = instruction_start + deopt_data->Pc(i)->value(); 782b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // There is room enough to write a long call instruction because we pad 792b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch // LLazyBailout instructions with nops if necessary. 802b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch CodePatcher patcher(call_address, Assembler::kCallInstructionLength); 812b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch patcher.masm()->Call(GetDeoptimizationEntry(i, LAZY), RelocInfo::NONE); 822b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(prev_call_address == NULL || 832b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch call_address >= prev_call_address + patch_size()); 842b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch ASSERT(call_address + patch_size() <= code->instruction_end()); 853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifdef DEBUG 862b4ba1175df6a5a6b9b5cda034189197bf6565ecBen Murdoch prev_call_address = call_address; 873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif 881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Isolate* isolate = code->GetIsolate(); 911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Add the deoptimizing code to the list. 931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizingCodeListNode* node = new DeoptimizingCodeListNode(code); 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeoptimizerData* data = isolate->deoptimizer_data(); 9544f0eee88ff00398ff7f715fab053374d808c90dSteve Block node->set_next(data->deoptimizing_code_list_); 9644f0eee88ff00398ff7f715fab053374d808c90dSteve Block data->deoptimizing_code_list_ = node; 971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We might be in the middle of incremental marking with compaction. 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Tell collector to treat this code object in a special way and 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // ignore all slots that might have been recorded on it. 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate->heap()->mark_compact_collector()->InvalidateCode(code); 1023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the code for the function to non-optimized version. 1041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block function->ReplaceCode(function->shared()->code()); 1051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_trace_deopt) { 1071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF("[forced deoptimization: "); 1081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block function->PrintName(); 1091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" / %" V8PRIxPTR "]\n", reinterpret_cast<intptr_t>(function)); 1101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::PatchStackCheckCodeAt(Code* unoptimized_code, 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address pc_after, 1161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* check_code, 1171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* replacement_code) { 118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Address call_target_address = pc_after - kIntSize; 119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(check_code->entry() == 120e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Assembler::target_address_at(call_target_address)); 121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The stack check code matches the pattern: 122e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // 123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // cmp rsp, <limit> 124e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // jae ok 125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // call <stack guard> 126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // test rax, <loop nesting depth> 127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // ok: ... 128e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // 129e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We will patch away the branch so the code is: 130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // 131e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // cmp rsp, <limit> ;; Not changed 132e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // nop 133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // nop 134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // call <on-stack replacment> 135e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // test rax, <loop nesting depth> 136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // ok: 137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // 138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(*(call_target_address - 3) == 0x73 && // jae 139e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *(call_target_address - 2) == 0x07 && // offset 140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *(call_target_address - 1) == 0xe8); // call 1413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *(call_target_address - 3) = 0x66; // 2 byte nop part 1 1423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *(call_target_address - 2) = 0x90; // 2 byte nop part 2 143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Assembler::set_target_address_at(call_target_address, 144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch replacement_code->entry()); 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unoptimized_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 1473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unoptimized_code, call_target_address, replacement_code); 148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::RevertStackCheckCodeAt(Code* unoptimized_code, 1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address pc_after, 1531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* check_code, 1541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* replacement_code) { 155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Address call_target_address = pc_after - kIntSize; 156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(replacement_code->entry() == 157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Assembler::target_address_at(call_target_address)); 158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Replace the nops from patching (Deoptimizer::PatchStackCheckCode) to 159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // restore the conditional branch. 1603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(*(call_target_address - 3) == 0x66 && // 2 byte nop part 1 1613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *(call_target_address - 2) == 0x90 && // 2 byte nop part 2 162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *(call_target_address - 1) == 0xe8); // call 163e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *(call_target_address - 3) = 0x73; // jae 164e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *(call_target_address - 2) = 0x07; // offset 165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Assembler::set_target_address_at(call_target_address, 166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch check_code->entry()); 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check_code->GetHeap()->incremental_marking()->RecordCodeTargetPatch( 1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unoptimized_code, call_target_address, check_code); 170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochstatic int LookupBailoutId(DeoptimizationInputData* data, unsigned ast_id) { 174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ByteArray* translations = data->TranslationByteArray(); 175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int length = data->DeoptCount(); 176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < length; i++) { 177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (static_cast<unsigned>(data->AstId(i)->value()) == ast_id) { 178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranslationIterator it(translations, data->TranslationIndex(i)->value()); 179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int value = it.Next(); 180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(Translation::BEGIN == static_cast<Translation::Opcode>(value)); 181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Read the number of frames. 182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch value = it.Next(); 183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (value == 1) return i; 184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch UNREACHABLE(); 187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return -1; 188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DoComputeOsrOutputFrame() { 192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch DeoptimizationInputData* data = DeoptimizationInputData::cast( 193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch optimized_code_->deoptimization_data()); 194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned ast_id = data->OsrAstId()->value(); 195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(kasperl): This should not be the bailout_id_. It should be 196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the ast id. Confusing. 197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(bailout_id_ == ast_id); 198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int bailout_id = LookupBailoutId(data, ast_id); 200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned translation_index = data->TranslationIndex(bailout_id)->value(); 201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ByteArray* translations = data->TranslationByteArray(); 202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TranslationIterator iterator(translations, translation_index); 204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Translation::Opcode opcode = 205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch static_cast<Translation::Opcode>(iterator.Next()); 206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(Translation::BEGIN == opcode); 207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch USE(opcode); 208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int count = iterator.Next(); 2093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch iterator.Skip(1); // Drop JS frame count. 210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(count == 1); 211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch USE(count); 212e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 213e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch opcode = static_cast<Translation::Opcode>(iterator.Next()); 214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch USE(opcode); 2153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(Translation::JS_FRAME == opcode); 216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned node_id = iterator.Next(); 217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch USE(node_id); 218e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(node_id == ast_id); 219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch JSFunction* function = JSFunction::cast(ComputeLiteral(iterator.Next())); 220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch USE(function); 221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(function == function_); 222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned height = iterator.Next(); 223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned height_in_bytes = height * kPointerSize; 224e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch USE(height_in_bytes); 225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned fixed_size = ComputeFixedSize(function_); 2273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unsigned input_frame_size = input_->GetFrameSize(); 228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(fixed_size + height_in_bytes == input_frame_size); 229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; 231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); 232e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned outgoing_size = outgoing_height * kPointerSize; 233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; 234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. 235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_trace_osr) { 237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", 238e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch reinterpret_cast<intptr_t>(function_)); 239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch function_->PrintName(); 240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF(" => node=%u, frame=%d->%d]\n", 241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_id, 242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch input_frame_size, 243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_frame_size); 244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 245e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 246e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // There's only one output frame in the OSR case. 247e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_count_ = 1; 248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_ = new FrameDescription*[1]; 249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_[0] = new(output_frame_size) FrameDescription( 250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_frame_size, function_); 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_[0]->SetFrameType(StackFrame::JAVA_SCRIPT); 252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Clear the incoming parameters in the optimized frame to avoid 254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // confusing the garbage collector. 255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned output_offset = output_frame_size - kPointerSize; 256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int parameter_count = function_->shared()->formal_parameter_count() + 1; 257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < parameter_count; ++i) { 258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_[0]->SetFrameSlot(output_offset, 0); 259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_offset -= kPointerSize; 260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Translate the incoming parameters. This may overwrite some of the 263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // incoming argument slots we've just cleared. 264e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int input_offset = input_frame_size - kPointerSize; 265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bool ok = true; 266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int limit = input_offset - (parameter_count * kPointerSize); 267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (ok && input_offset > limit) { 268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ok = DoOsrTranslateCommand(&iterator, &input_offset); 269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // There are no translation commands for the caller's pc and fp, the 272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // context, and the function. Set them up explicitly. 27344f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = StandardFrameConstants::kCallerPCOffset; 27444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ok && i >= StandardFrameConstants::kMarkerOffset; 27544f0eee88ff00398ff7f715fab053374d808c90dSteve Block i -= kPointerSize) { 276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch intptr_t input_value = input_->GetFrameSlot(input_offset); 277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_trace_osr) { 27844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const char* name = "UNKNOWN"; 27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block switch (i) { 28044f0eee88ff00398ff7f715fab053374d808c90dSteve Block case StandardFrameConstants::kCallerPCOffset: 28144f0eee88ff00398ff7f715fab053374d808c90dSteve Block name = "caller's pc"; 28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 28344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case StandardFrameConstants::kCallerFPOffset: 28444f0eee88ff00398ff7f715fab053374d808c90dSteve Block name = "fp"; 28544f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 28644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case StandardFrameConstants::kContextOffset: 28744f0eee88ff00398ff7f715fab053374d808c90dSteve Block name = "context"; 28844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block case StandardFrameConstants::kMarkerOffset: 29044f0eee88ff00398ff7f715fab053374d808c90dSteve Block name = "function"; 29144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 29244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 29344f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF(" [rsp + %d] <- 0x%08" V8PRIxPTR " ; [rsp + %d] " 29444f0eee88ff00398ff7f715fab053374d808c90dSteve Block "(fixed part - %s)\n", 295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_offset, 296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch input_value, 29744f0eee88ff00398ff7f715fab053374d808c90dSteve Block input_offset, 29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block name); 299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_[0]->SetFrameSlot(output_offset, input_->GetFrameSlot(input_offset)); 301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch input_offset -= kPointerSize; 302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_offset -= kPointerSize; 303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Translate the rest of the frame. 306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (ok && input_offset >= 0) { 307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ok = DoOsrTranslateCommand(&iterator, &input_offset); 308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If translation of any command failed, continue using the input frame. 311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!ok) { 312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch delete output_[0]; 313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_[0] = input_; 314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_[0]->SetPc(reinterpret_cast<intptr_t>(from_)); 315e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the frame pointer and the context pointer. 317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_[0]->SetRegister(rbp.code(), input_->GetRegister(rbp.code())); 318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_[0]->SetRegister(rsi.code(), input_->GetRegister(rsi.code())); 319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch unsigned pc_offset = data->OsrPcOffset()->value(); 321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch intptr_t pc = reinterpret_cast<intptr_t>( 322e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch optimized_code_->entry() + pc_offset); 323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_[0]->SetPc(pc); 324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Code* continuation = 32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block function->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); 327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch output_[0]->SetContinuation( 328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch reinterpret_cast<intptr_t>(continuation->entry())); 329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_trace_osr) { 331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", 332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ok ? "finished" : "aborted", 333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch reinterpret_cast<intptr_t>(function)); 334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch function->PrintName(); 335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF(" => pc=0x%0" V8PRIxPTR "]\n", output_[0]->GetPc()); 336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::DoComputeArgumentsAdaptorFrame(TranslationIterator* iterator, 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int frame_index) { 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned height = iterator->Next(); 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned height_in_bytes = height * kPointerSize; 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" translating arguments adaptor => height=%d\n", height_in_bytes); 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned fixed_frame_size = ArgumentsAdaptorFrameConstants::kFrameSize; 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned output_frame_size = height_in_bytes + fixed_frame_size; 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate and store the output frame description. 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameDescription* output_frame = 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(output_frame_size) FrameDescription(output_frame_size, function); 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameType(StackFrame::ARGUMENTS_ADAPTOR); 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Arguments adaptor can not be topmost or bottommost. 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(frame_index > 0 && frame_index < output_count_ - 1); 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(output_[frame_index] == NULL); 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_[frame_index] = output_frame; 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The top address of the frame is computed from the previous 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // frame's top and this frame's size. 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t top_address; 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetTop(top_address); 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the incoming parameter translation. 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int parameter_count = height; 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned output_offset = output_frame_size; 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < parameter_count; ++i) { 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoTranslateCommand(iterator, frame_index, output_offset); 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Read caller's PC from the previous frame. 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 3783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t callers_pc = output_[frame_index - 1]->GetPc(); 3793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, callers_pc); 3803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 3813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 3823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; caller's pc\n", 3833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, callers_pc); 3843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Read caller's FP from the previous frame, and set this frame's FP. 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t value = output_[frame_index - 1]->GetFp(); 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t fp_value = top_address + output_offset; 3913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFp(fp_value); 3923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 3933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 3943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; caller's fp\n", 3953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fp_value, output_offset, value); 3963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A marker value is used in place of the context. 3993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t context = reinterpret_cast<intptr_t>( 4013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); 4023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, context); 4033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 4053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; context (adaptor sentinel)\n", 4063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, context); 4073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The function was mentioned explicitly in the ARGUMENTS_ADAPTOR_FRAME. 4103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = reinterpret_cast<intptr_t>(function); 4123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 4133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 4153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; function\n", 4163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value); 4173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Number of incoming arguments. 4203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1)); 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 4233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 4253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; argc (%d)\n", 4263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value, height - 1); 4273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(0 == output_offset); 4303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Builtins* builtins = isolate_->builtins(); 4323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Code* adaptor_trampoline = 4333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t pc_value = reinterpret_cast<intptr_t>( 4353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch adaptor_trampoline->instruction_start() + 4363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); 4373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetPc(pc_value); 4383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 4393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, 4423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int frame_index) { 4439413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch Builtins* builtins = isolate_->builtins(); 4449413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned height = iterator->Next(); 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned height_in_bytes = height * kPointerSize; 4483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" translating construct stub => height=%d\n", height_in_bytes); 4503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4529413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch unsigned fixed_frame_size = 7 * kPointerSize; 4533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned output_frame_size = height_in_bytes + fixed_frame_size; 4543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Allocate and store the output frame description. 4563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameDescription* output_frame = 4573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(output_frame_size) FrameDescription(output_frame_size, function); 4583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameType(StackFrame::CONSTRUCT); 4593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Construct stub can not be topmost or bottommost. 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(frame_index > 0 && frame_index < output_count_ - 1); 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(output_[frame_index] == NULL); 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_[frame_index] = output_frame; 4643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The top address of the frame is computed from the previous 4663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // frame's top and this frame's size. 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t top_address; 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetTop(top_address); 4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the incoming parameter translation. 4723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int parameter_count = height; 4733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch unsigned output_offset = output_frame_size; 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < parameter_count; ++i) { 4753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DoTranslateCommand(iterator, frame_index, output_offset); 4773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Read caller's PC from the previous frame. 4803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t callers_pc = output_[frame_index - 1]->GetPc(); 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, callers_pc); 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; caller's pc\n", 4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, callers_pc); 4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Read caller's FP from the previous frame, and set this frame's FP. 4903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 4913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t value = output_[frame_index - 1]->GetFp(); 4923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 4933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t fp_value = top_address + output_offset; 4943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFp(fp_value); 4953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 4963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 4973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; caller's fp\n", 4983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fp_value, output_offset, value); 4993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The context can be gotten from the previous frame. 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = output_[frame_index - 1]->GetContext(); 5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; context\n", 5083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value); 5093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A marker value is used in place of the function. 5123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 5133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT)); 5143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 5173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; function (construct sentinel)\n", 5183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value); 5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5219413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch // The output frame reflects a JSConstructStubGeneric frame. 5229413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch output_offset -= kPointerSize; 5239413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch value = reinterpret_cast<intptr_t>(construct_stub); 5249413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5259413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch if (FLAG_trace_deopt) { 5269413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 5279413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch V8PRIxPTR " ; code object\n", 5289413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch top_address + output_offset, output_offset, value); 5299413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch } 5309413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch 5313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Number of incoming arguments. 5323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 5333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1)); 5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; argc (%d)\n", 5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value, height - 1); 5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The newly allocated object was passed as receiver in the artificial 5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // constructor stub environment created by HEnvironment::CopyForInlining(). 5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_offset -= kPointerSize; 5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); 5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameSlot(output_offset, value); 5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_deopt) { 5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch V8PRIxPTR " ; allocated receiver\n", 5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch top_address + output_offset, output_offset, value); 5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(0 == output_offset); 5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch intptr_t pc = reinterpret_cast<intptr_t>( 5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch construct_stub->instruction_start() + 5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate_->heap()->construct_stub_deopt_pc_offset()->value()); 5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetPc(pc); 5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid Deoptimizer::DoComputeJSFrame(TranslationIterator* iterator, 5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int frame_index) { 5631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int node_id = iterator->Next(); 5641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); 5651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned height = iterator->Next(); 5661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned height_in_bytes = height * kPointerSize; 5671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_trace_deopt) { 5681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" translating "); 5691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block function->PrintName(); 5701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" => node=%d, height=%d\n", node_id, height_in_bytes); 5711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 5721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 5731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The 'fixed' part of the frame consists of the incoming parameters and 5741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the part described by JavaScriptFrameConstants. 5751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned fixed_frame_size = ComputeFixedSize(function); 5763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch unsigned input_frame_size = input_->GetFrameSize(); 5771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned output_frame_size = height_in_bytes + fixed_frame_size; 5781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 5791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate and store the output frame description. 5801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FrameDescription* output_frame = 5811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block new(output_frame_size) FrameDescription(output_frame_size, function); 5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetFrameType(StackFrame::JAVA_SCRIPT); 5831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 5841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool is_bottommost = (0 == frame_index); 5851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool is_topmost = (output_count_ - 1 == frame_index); 5861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(frame_index >= 0 && frame_index < output_count_); 5871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(output_[frame_index] == NULL); 5881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_[frame_index] = output_frame; 5891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 5901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The top address for the bottommost output frame can be computed from 5911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the input frame pointer and the output frame's height. For all 5921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // subsequent output frames, it can be computed from the previous one's 5931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // top address and the current frame's size. 5941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block intptr_t top_address; 5951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (is_bottommost) { 5961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // 2 = context and function in the frame. 5971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block top_address = 5981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block input_->GetRegister(rbp.code()) - (2 * kPointerSize) - height_in_bytes; 5991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 6001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block top_address = output_[frame_index - 1]->GetTop() - output_frame_size; 6011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame->SetTop(top_address); 6031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compute the incoming parameter translation. 6051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int parameter_count = function->shared()->formal_parameter_count() + 1; 6061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned output_offset = output_frame_size; 6071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned input_offset = input_frame_size; 6081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < parameter_count; ++i) { 6091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_offset -= kPointerSize; 6101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DoTranslateCommand(iterator, frame_index, output_offset); 6111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block input_offset -= (parameter_count * kPointerSize); 6131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // There are no translation commands for the caller's pc and fp, the 6151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // context, and the function. Synthesize their values and set them up 6161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // explicitly. 6171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // 6181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The caller's pc for the bottommost output frame is the same as in the 6191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // input frame. For all subsequent output frames, it can be read from the 6201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // previous one. This frame's pc can be computed from the non-optimized 6211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // function code and AST id of the bailout. 6221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_offset -= kPointerSize; 6231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block input_offset -= kPointerSize; 6241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block intptr_t value; 6251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (is_bottommost) { 6261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = input_->GetFrameSlot(input_offset); 6271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 6281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = output_[frame_index - 1]->GetPc(); 6291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame->SetFrameSlot(output_offset, value); 6311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_trace_deopt) { 6321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 6331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block V8PRIxPTR " ; caller's pc\n", 6341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block top_address + output_offset, output_offset, value); 6351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The caller's frame pointer for the bottommost output frame is the same 6381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // as in the input frame. For all subsequent output frames, it can be 6391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // read from the previous one. Also compute and set this frame's frame 6401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // pointer. 6411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_offset -= kPointerSize; 6421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block input_offset -= kPointerSize; 6431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (is_bottommost) { 6441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = input_->GetFrameSlot(input_offset); 6451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 6461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = output_[frame_index - 1]->GetFp(); 6471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame->SetFrameSlot(output_offset, value); 6491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block intptr_t fp_value = top_address + output_offset; 6501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!is_bottommost || input_->GetRegister(rbp.code()) == fp_value); 6511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame->SetFp(fp_value); 6521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (is_topmost) output_frame->SetRegister(rbp.code(), fp_value); 6531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_trace_deopt) { 6541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 6551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block V8PRIxPTR " ; caller's fp\n", 6561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block fp_value, output_offset, value); 6571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 659e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // For the bottommost output frame the context can be gotten from the input 660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // frame. For all subsequent output frames it can be gotten from the function 661e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // so long as we don't inline functions that need local contexts. 6621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_offset -= kPointerSize; 6631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block input_offset -= kPointerSize; 664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (is_bottommost) { 665e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch value = input_->GetFrameSlot(input_offset); 666e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 667e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch value = reinterpret_cast<intptr_t>(function->context()); 668e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 6691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame->SetFrameSlot(output_offset, value); 6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch output_frame->SetContext(value); 6711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (is_topmost) output_frame->SetRegister(rsi.code(), value); 6721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_trace_deopt) { 6731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 6741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block V8PRIxPTR "; context\n", 6751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block top_address + output_offset, output_offset, value); 6761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The function was mentioned explicitly in the BEGIN_FRAME. 6791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_offset -= kPointerSize; 6801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block input_offset -= kPointerSize; 6811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = reinterpret_cast<intptr_t>(function); 6821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The function for the bottommost output frame should also agree with the 6831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // input frame. 6841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!is_bottommost || input_->GetFrameSlot(input_offset) == value); 6851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame->SetFrameSlot(output_offset, value); 6861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_trace_deopt) { 6871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" 6881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block V8PRIxPTR "; function\n", 6891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block top_address + output_offset, output_offset, value); 6901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Translate the rest of the frame. 6931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (unsigned i = 0; i < height; ++i) { 6941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_offset -= kPointerSize; 6951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DoTranslateCommand(iterator, frame_index, output_offset); 6961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(0 == output_offset); 6981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compute this frame's PC, state, and continuation. 7001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* non_optimized_code = function->shared()->code(); 7011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FixedArray* raw_data = non_optimized_code->deoptimization_data(); 7021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block DeoptimizationOutputData* data = DeoptimizationOutputData::cast(raw_data); 7031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Address start = non_optimized_code->instruction_start(); 7041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned pc_and_state = GetOutputInfo(data, node_id, function->shared()); 7051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unsigned pc_offset = FullCodeGenerator::PcField::decode(pc_and_state); 7061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block intptr_t pc_value = reinterpret_cast<intptr_t>(start + pc_offset); 7071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame->SetPc(pc_value); 7081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FullCodeGenerator::State state = 7101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block FullCodeGenerator::StateField::decode(pc_and_state); 7111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame->SetState(Smi::FromInt(state)); 7121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the continuation for the topmost frame. 7143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_topmost && bailout_type_ != DEBUGGER) { 7151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* continuation = (bailout_type_ == EAGER) 71644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? isolate_->builtins()->builtin(Builtins::kNotifyDeoptimized) 71744f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_->builtins()->builtin(Builtins::kNotifyLazyDeoptimized); 7181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block output_frame->SetContinuation( 7191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block reinterpret_cast<intptr_t>(continuation->entry())); 7201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { 7253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Set the register values. The values are not important as there are no 7263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // callee saved registers in JavaScript frames, so all registers are 7273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // spilled. Registers rbp and rsp are set to the correct values though. 7283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < Register::kNumRegisters; i++) { 7293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch input_->SetRegister(i, i * 4); 7303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch input_->SetRegister(rsp.code(), reinterpret_cast<intptr_t>(frame->sp())); 7323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch input_->SetRegister(rbp.code(), reinterpret_cast<intptr_t>(frame->fp())); 7333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) { 7343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch input_->SetDoubleRegister(i, 0.0); 7353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Fill the frame content from the actual data on the frame. 7383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { 7393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch input_->SetFrameSlot(i, Memory::uint64_at(tos + i)); 7403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 7423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 7441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#define __ masm()-> 7451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::EntryGenerator::Generate() { 7471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GeneratePrologue(); 7481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Save all general purpose registers before messing with them. 7501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int kNumberOfRegisters = Register::kNumRegisters; 7511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int kDoubleRegsSize = kDoubleSize * 7531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister::kNumAllocatableRegisters; 7541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ subq(rsp, Immediate(kDoubleRegsSize)); 7551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { 7571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); 7581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = i * kDoubleSize; 7591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(Operand(rsp, offset), xmm_reg); 7601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We push all registers onto the stack, even though we do not need 7631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to restore all later. 7641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < kNumberOfRegisters; i++) { 7653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r = Register::from_code(i); 7661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(r); 7671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 7681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + 7701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block kDoubleRegsSize; 7711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // When calling new_deoptimizer_function we need to pass the last argument 7731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // on the stack on windows and in r8 on linux. The remaining arguments are 7741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // all passed in registers (different ones on linux and windows though). 7751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef _WIN64 7771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register arg4 = r9; 7781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register arg3 = r8; 7791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register arg2 = rdx; 7801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register arg1 = rcx; 7811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#else 7821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register arg4 = rcx; 7831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register arg3 = rdx; 7841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register arg2 = rsi; 7851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register arg1 = rdi; 7861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 7871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We use this to keep the value of the fifth argument temporarily. 7891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unfortunately we can't store it directly in r8 (used for passing 7901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // this on linux), since it is another parameter passing register on windows. 7911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Register arg5 = r11; 7921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Get the bailout id from the stack. 7941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(arg3, Operand(rsp, kSavedRegistersAreaSize)); 7951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 7961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Get the address of the location in the code object if possible 7971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // and compute the fp-to-sp delta in register arg5. 7981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (type() == EAGER) { 7991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Set(arg4, 0); 8001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ lea(arg5, Operand(rsp, kSavedRegistersAreaSize + 1 * kPointerSize)); 8011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 8021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(arg4, Operand(rsp, kSavedRegistersAreaSize + 1 * kPointerSize)); 8031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ lea(arg5, Operand(rsp, kSavedRegistersAreaSize + 2 * kPointerSize)); 8041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 8051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ subq(arg5, rbp); 8071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ neg(arg5); 8081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a new deoptimizer object. 8108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ PrepareCallCFunction(6); 8111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, Operand(rbp, JavaScriptFrameConstants::kFunctionOffset)); 8121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(arg1, rax); 8138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(arg2, type()); 8141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Args 3 and 4 are already in the right registers. 8151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // On windows put the arguments on the stack (PrepareCallCFunction 8178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // has created space for this). On linux pass the arguments in r8 and r9. 8181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#ifdef _WIN64 819e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ movq(Operand(rsp, 4 * kPointerSize), arg5); 8208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ LoadAddress(arg5, ExternalReference::isolate_address()); 8218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ movq(Operand(rsp, 5 * kPointerSize), arg5); 8221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#else 8231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(r8, arg5); 8248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ LoadAddress(r9, ExternalReference::isolate_address()); 8251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#endif 8261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 82744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = masm()->isolate(); 82844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm()); 8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction(ExternalReference::new_deoptimizer_function(isolate), 6); 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Preserve deoptimizer object in register rax and get the input 8341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // frame descriptor pointer. 8351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rbx, Operand(rax, Deoptimizer::input_offset())); 8361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Fill in the input registers. 8381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = kNumberOfRegisters -1; i >= 0; i--) { 8391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = (i * kPointerSize) + FrameDescription::registers_offset(); 8401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(Operand(rbx, offset)); 8411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 8421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Fill in the double input registers. 8441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int double_regs_offset = FrameDescription::double_registers_offset(); 8451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; i++) { 8461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int dst_offset = i * kDoubleSize + double_regs_offset; 8471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(Operand(rbx, dst_offset)); 8481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 8491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Remove the bailout id from the stack. 8511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (type() == EAGER) { 8521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ addq(rsp, Immediate(kPointerSize)); 8531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 8541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ addq(rsp, Immediate(2 * kPointerSize)); 8551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 8561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compute a pointer to the unwinding limit in register rcx; that is 8581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the first stack slot not part of the input frame. 8591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rcx, Operand(rbx, FrameDescription::frame_size_offset())); 8601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ addq(rcx, rsp); 8611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unwind the stack down to - but not including - the unwinding 8631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // limit and copy the contents of the activation frame to the input 8641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // frame description. 8651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ lea(rdx, Operand(rbx, FrameDescription::frame_content_offset())); 8661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label pop_loop; 8671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&pop_loop); 8681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(Operand(rdx, 0)); 8691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ addq(rdx, Immediate(sizeof(intptr_t))); 8701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpq(rcx, rsp); 8711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_equal, &pop_loop); 8721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Compute the output frame in the deoptimizer. 8741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(rax); 8758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ PrepareCallCFunction(2); 8761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(arg1, rax); 8778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ LoadAddress(arg2, ExternalReference::isolate_address()); 8783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 8793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm()); 8803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallCFunction( 8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference::compute_output_frames_function(isolate), 2); 8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(rax); 8841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Replace the current frame with the output frames. 8861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label outer_push_loop, inner_push_loop; 8871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Outer loop state: rax = current FrameDescription**, rdx = one past the 8881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // last FrameDescription**. 8891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movl(rdx, Operand(rax, Deoptimizer::output_count_offset())); 8901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, Operand(rax, Deoptimizer::output_offset())); 8911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ lea(rdx, Operand(rax, rdx, times_8, 0)); 8921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&outer_push_loop); 8931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Inner loop state: rbx = current FrameDescription*, rcx = loop index. 8941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rbx, Operand(rax, 0)); 8951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rcx, Operand(rbx, FrameDescription::frame_size_offset())); 8961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&inner_push_loop); 8971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ subq(rcx, Immediate(sizeof(intptr_t))); 8981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(Operand(rbx, rcx, times_1, FrameDescription::frame_content_offset())); 8991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ testq(rcx, rcx); 9001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_zero, &inner_push_loop); 9011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ addq(rax, Immediate(kPointerSize)); 9021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpq(rax, rdx); 9031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(below, &outer_push_loop); 9041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // In case of OSR, we have to restore the XMM registers. 9061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (type() == OSR) { 9071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { 9081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); 9091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int src_offset = i * kDoubleSize + double_regs_offset; 9101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(xmm_reg, Operand(rbx, src_offset)); 9111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Push state, pc, and continuation from the last output frame. 9151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (type() != OSR) { 9161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(Operand(rbx, FrameDescription::state_offset())); 9171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(Operand(rbx, FrameDescription::pc_offset())); 9191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(Operand(rbx, FrameDescription::continuation_offset())); 9201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Push the registers from the last output frame. 9221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < kNumberOfRegisters; i++) { 9231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int offset = (i * kPointerSize) + FrameDescription::registers_offset(); 9241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push(Operand(rbx, offset)); 9251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Restore the registers from the stack. 9281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = kNumberOfRegisters - 1; i >= 0 ; i--) { 9293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register r = Register::from_code(i); 9301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Do not restore rsp, simply pop the value into the next register 9311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // and overwrite this afterwards. 9321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (r.is(rsp)) { 9331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(i > 0); 9343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch r = Register::from_code(i - 1); 9351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ pop(r); 9371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set up the roots register. 940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ InitializeRootRegister(); 941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ InitializeSmiConstantRegister(); 9421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Return to the continuation point. 9441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::TableEntryGenerator::GeneratePrologue() { 9491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Create a sequence of deoptimization entries. 9501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label done; 9511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < count(); i++) { 9521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int start = masm()->pc_offset(); 9531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block USE(start); 9541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ push_imm32(i); 9551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ jmp(&done); 9561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(masm()->pc_offset() - start == table_entry_size_); 9571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 9581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&done); 95981362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen} 96081362e16c30e9e970af6b17592f627ad8cdee4d8Kristian Monsen 9611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#undef __ 9621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 9631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} } // namespace v8::internal 965b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 966b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch#endif // V8_TARGET_ARCH_X64 967