deoptimizer.cc revision 8b112d2025046f85ef7f6be087c6129c872ebad2
1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2010 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 "disasm.h" 33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h" 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "global-handles.h" 35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "macro-assembler.h" 36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "prettyprinter.h" 37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 { 40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal { 41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4244f0eee88ff00398ff7f715fab053374d808c90dSteve BlockDeoptimizerData::DeoptimizerData() { 4344f0eee88ff00398ff7f715fab053374d808c90dSteve Block eager_deoptimization_entry_code_ = NULL; 4444f0eee88ff00398ff7f715fab053374d808c90dSteve Block lazy_deoptimization_entry_code_ = NULL; 4544f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_ = NULL; 4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block deoptimizing_code_list_ = NULL; 4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockDeoptimizerData::~DeoptimizerData() { 5144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (eager_deoptimization_entry_code_ != NULL) { 5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block eager_deoptimization_entry_code_->Free(EXECUTABLE); 5344f0eee88ff00398ff7f715fab053374d808c90dSteve Block eager_deoptimization_entry_code_ = NULL; 5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (lazy_deoptimization_entry_code_ != NULL) { 5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block lazy_deoptimization_entry_code_->Free(EXECUTABLE); 5744f0eee88ff00398ff7f715fab053374d808c90dSteve Block lazy_deoptimization_entry_code_ = NULL; 5844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 6044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochDeoptimizer* Deoptimizer::New(JSFunction* function, 62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BailoutType type, 63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned bailout_id, 64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address from, 6544f0eee88ff00398ff7f715fab053374d808c90dSteve Block int fp_to_sp_delta, 6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate) { 6744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(isolate == Isolate::Current()); 6844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Deoptimizer* deoptimizer = new Deoptimizer(isolate, 6944f0eee88ff00398ff7f715fab053374d808c90dSteve Block function, 7044f0eee88ff00398ff7f715fab053374d808c90dSteve Block type, 7144f0eee88ff00398ff7f715fab053374d808c90dSteve Block bailout_id, 7244f0eee88ff00398ff7f715fab053374d808c90dSteve Block from, 7344f0eee88ff00398ff7f715fab053374d808c90dSteve Block fp_to_sp_delta); 7444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(isolate->deoptimizer_data()->current_ == NULL); 7544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->deoptimizer_data()->current_ = deoptimizer; 76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return deoptimizer; 77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8044f0eee88ff00398ff7f715fab053374d808c90dSteve BlockDeoptimizer* Deoptimizer::Grab(Isolate* isolate) { 8144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(isolate == Isolate::Current()); 8244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Deoptimizer* result = isolate->deoptimizer_data()->current_; 83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(result != NULL); 84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->DeleteFrameDescriptions(); 8544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->deoptimizer_data()->current_ = NULL; 86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::GenerateDeoptimizationEntries(MacroAssembler* masm, 91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int count, 92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BailoutType type) { 93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TableEntryGenerator generator(masm, type, count); 94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch generator.Generate(); 95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass DeoptimizingVisitor : public OptimizedFunctionVisitor { 99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual void EnterContext(Context* context) { 101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[deoptimize context: %" V8PRIxPTR "]\n", 103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reinterpret_cast<intptr_t>(context)); 104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual void VisitFunction(JSFunction* function) { 108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Deoptimizer::DeoptimizeFunction(function); 109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch virtual void LeaveContext(Context* context) { 112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context->ClearOptimizedFunctions(); 113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DeoptimizeAll() { 118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssertNoAllocation no_allocation; 119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[deoptimize all contexts]\n"); 122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizingVisitor visitor; 125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitAllOptimizedFunctions(&visitor); 126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DeoptimizeGlobalObject(JSObject* object) { 130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssertNoAllocation no_allocation; 131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizingVisitor visitor; 133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitAllOptimizedFunctionsForGlobalObject(object, &visitor); 134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::VisitAllOptimizedFunctionsForContext( 138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Context* context, OptimizedFunctionVisitor* visitor) { 139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssertNoAllocation no_allocation; 140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(context->IsGlobalContext()); 142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visitor->EnterContext(context); 144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Run through the list of optimized functions and deoptimize them. 145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Object* element = context->OptimizedFunctionsListHead(); 146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!element->IsUndefined()) { 147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch JSFunction* element_function = JSFunction::cast(element); 148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the next link before deoptimizing as deoptimizing will clear the 149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // next link. 150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch element = element_function->next_function_link(); 151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visitor->VisitFunction(element_function); 152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visitor->LeaveContext(context); 154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::VisitAllOptimizedFunctionsForGlobalObject( 158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch JSObject* object, OptimizedFunctionVisitor* visitor) { 159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssertNoAllocation no_allocation; 160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (object->IsJSGlobalProxy()) { 162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Object* proto = object->GetPrototype(); 163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(proto->IsJSGlobalObject()); 164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitAllOptimizedFunctionsForContext( 165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GlobalObject::cast(proto)->global_context(), visitor); 166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (object->IsGlobalObject()) { 167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitAllOptimizedFunctionsForContext( 168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GlobalObject::cast(object)->global_context(), visitor); 169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::VisitAllOptimizedFunctions( 174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch OptimizedFunctionVisitor* visitor) { 175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssertNoAllocation no_allocation; 176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Run through the list of all global contexts and deoptimize. 17844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Object* global = Isolate::Current()->heap()->global_contexts_list(); 179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!global->IsUndefined()) { 180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitAllOptimizedFunctionsForGlobalObject(Context::cast(global)->global(), 181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visitor); 182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch global = Context::cast(global)->get(Context::NEXT_CONTEXT_LINK); 183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::HandleWeakDeoptimizedCode( 188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch v8::Persistent<v8::Value> obj, void* data) { 189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizingCodeListNode* node = 190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reinterpret_cast<DeoptimizingCodeListNode*>(data); 191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RemoveDeoptimizingCode(*node->code()); 192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 19344f0eee88ff00398ff7f715fab053374d808c90dSteve Block node = Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_; 194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (node != NULL) { 195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(node != reinterpret_cast<DeoptimizingCodeListNode*>(data)); 196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch node = node->next(); 197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid Deoptimizer::ComputeOutputFrames(Deoptimizer* deoptimizer) { 203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch deoptimizer->DoComputeOutputFrames(); 204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 20744f0eee88ff00398ff7f715fab053374d808c90dSteve BlockDeoptimizer::Deoptimizer(Isolate* isolate, 20844f0eee88ff00398ff7f715fab053374d808c90dSteve Block JSFunction* function, 209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BailoutType type, 210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned bailout_id, 211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Address from, 212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int fp_to_sp_delta) 21344f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(isolate), 21444f0eee88ff00398ff7f715fab053374d808c90dSteve Block function_(function), 215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bailout_id_(bailout_id), 216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bailout_type_(type), 217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch from_(from), 218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch fp_to_sp_delta_(fp_to_sp_delta), 219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_count_(0), 220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_(NULL), 2218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch deferred_heap_numbers_(0) { 222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt && type != OSR) { 223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("**** DEOPT: "); 224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function->PrintName(); 225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" at bailout #%u, address 0x%" V8PRIxPTR ", frame size %d\n", 226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bailout_id, 227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reinterpret_cast<intptr_t>(from), 228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch fp_to_sp_delta - (2 * kPointerSize)); 229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (FLAG_trace_osr && type == OSR) { 230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("**** OSR: "); 231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function->PrintName(); 232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" at ast id #%u, address 0x%" V8PRIxPTR ", frame size %d\n", 233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bailout_id, 234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reinterpret_cast<intptr_t>(from), 235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch fp_to_sp_delta - (2 * kPointerSize)); 236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Find the optimized code. 238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (type == EAGER) { 239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(from == NULL); 240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch optimized_code_ = function_->code(); 241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (type == LAZY) { 242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch optimized_code_ = FindDeoptimizingCodeFromAddress(from); 243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(optimized_code_ != NULL); 244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (type == OSR) { 245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The function has already been optimized and we're transitioning 246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // from the unoptimized shared version to the optimized one in the 247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // function. The return address (from) points to unoptimized code. 248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch optimized_code_ = function_->code(); 249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(optimized_code_->kind() == Code::OPTIMIZED_FUNCTION); 250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!optimized_code_->contains(from)); 251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 25244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(HEAP->allow_allocation(false)); 253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned size = ComputeInputFrameSize(); 254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_ = new(size) FrameDescription(size, function); 255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochDeoptimizer::~Deoptimizer() { 259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(input_ == NULL && output_ == NULL); 260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DeleteFrameDescriptions() { 264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch delete input_; 265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < output_count_; ++i) { 266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (output_[i] != input_) delete output_[i]; 267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch delete[] output_; 269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_ = NULL; 270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_ = NULL; 27144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!HEAP->allow_allocation(true)); 272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAddress Deoptimizer::GetDeoptimizationEntry(int id, BailoutType type) { 276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(id >= 0); 277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (id >= kNumberOfEntries) return NULL; 278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LargeObjectChunk* base = NULL; 27944f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizerData* data = Isolate::Current()->deoptimizer_data(); 280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (type == EAGER) { 28144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (data->eager_deoptimization_entry_code_ == NULL) { 28244f0eee88ff00398ff7f715fab053374d808c90dSteve Block data->eager_deoptimization_entry_code_ = CreateCode(type); 283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 28444f0eee88ff00398ff7f715fab053374d808c90dSteve Block base = data->eager_deoptimization_entry_code_; 285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 28644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (data->lazy_deoptimization_entry_code_ == NULL) { 28744f0eee88ff00398ff7f715fab053374d808c90dSteve Block data->lazy_deoptimization_entry_code_ = CreateCode(type); 288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 28944f0eee88ff00398ff7f715fab053374d808c90dSteve Block base = data->lazy_deoptimization_entry_code_; 290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<Address>(base->GetStartAddress()) + (id * table_entry_size_); 293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint Deoptimizer::GetDeoptimizationId(Address addr, BailoutType type) { 297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LargeObjectChunk* base = NULL; 29844f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizerData* data = Isolate::Current()->deoptimizer_data(); 299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (type == EAGER) { 30044f0eee88ff00398ff7f715fab053374d808c90dSteve Block base = data->eager_deoptimization_entry_code_; 301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 30244f0eee88ff00398ff7f715fab053374d808c90dSteve Block base = data->lazy_deoptimization_entry_code_; 303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (base == NULL || 305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch addr < base->GetStartAddress() || 306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch addr >= base->GetStartAddress() + 307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (kNumberOfEntries * table_entry_size_)) { 308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return kNotDeoptimizationEntry; 309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(0, 311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(addr - base->GetStartAddress()) % table_entry_size_); 312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return static_cast<int>(addr - base->GetStartAddress()) / table_entry_size_; 313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockint Deoptimizer::GetOutputInfo(DeoptimizationOutputData* data, 3179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block unsigned id, 3189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block SharedFunctionInfo* shared) { 319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(kasperl): For now, we do a simple linear search for the PC 320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // offset associated with the given node id. This should probably be 321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // changed to a binary search. 322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = data->DeoptPoints(); 323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Smi* smi_id = Smi::FromInt(id); 324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; i++) { 325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (data->AstId(i) == smi_id) { 326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return data->PcAndState(i)->value(); 327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[couldn't find pc offset for node=%u]\n", id); 330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[method: %s]\n", *shared->DebugName()->ToCString()); 331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Print the source code if available. 332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HeapStringAllocator string_allocator; 333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StringStream stream(&string_allocator); 334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch shared->SourceCodePrint(&stream, -1); 335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[source:\n%s\n]", *stream.ToCString()); 336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return -1; 339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 34244f0eee88ff00398ff7f715fab053374d808c90dSteve Blockint Deoptimizer::GetDeoptimizedCodeCount(Isolate* isolate) { 343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = 0; 34444f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizingCodeListNode* node = 34544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate->deoptimizer_data()->deoptimizing_code_list_; 346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (node != NULL) { 347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch length++; 348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch node = node->next(); 349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return length; 351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DoComputeOutputFrames() { 355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (bailout_type_ == OSR) { 356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoComputeOsrOutputFrame(); 357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Print some helpful diagnostic information. 361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int64_t start = OS::Ticks(); 362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[deoptimizing%s: begin 0x%08" V8PRIxPTR " ", 364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (bailout_type_ == LAZY ? " (lazy)" : ""), 365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reinterpret_cast<intptr_t>(function_)); 366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function_->PrintName(); 367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" @%d]\n", bailout_id_); 368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Determine basic deoptimization information. The optimized frame is 371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // described by the input data. 372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizationInputData* input_data = 373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizationInputData::cast(optimized_code_->deoptimization_data()); 374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned node_id = input_data->AstId(bailout_id_)->value(); 375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ByteArray* translations = input_data->TranslationByteArray(); 376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned translation_index = 377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_data->TranslationIndex(bailout_id_)->value(); 378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do the input frame to output frame(s) translation. 380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TranslationIterator iterator(translations, translation_index); 381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Translation::Opcode opcode = 382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<Translation::Opcode>(iterator.Next()); 383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(Translation::BEGIN == opcode); 384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch USE(opcode); 385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Read the number of output frames and allocate an array for their 386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // descriptions. 387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int count = iterator.Next(); 388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(output_ == NULL); 389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_ = new FrameDescription*[count]; 390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < count; ++i) { 391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[i] = NULL; 392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_count_ = count; 394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Translate each output frame. 396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < count; ++i) { 397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoComputeFrame(&iterator, i); 398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Print some helpful diagnostic information. 401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double ms = static_cast<double>(OS::Ticks() - start) / 1000; 403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = output_count_ - 1; // Index of the topmost frame. 404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch JSFunction* function = output_[index]->GetFunction(); 405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[deoptimizing: end 0x%08" V8PRIxPTR " ", 406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reinterpret_cast<intptr_t>(function)); 407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function->PrintName(); 408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" => node=%u, pc=0x%08" V8PRIxPTR ", state=%s, took %0.3f ms]\n", 409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch node_id, 410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[index]->GetPc(), 411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FullCodeGenerator::State2String( 412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<FullCodeGenerator::State>( 413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[index]->GetState()->value())), 414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ms); 415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid Deoptimizer::MaterializeHeapNumbers() { 4208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (int i = 0; i < deferred_heap_numbers_.length(); i++) { 4218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HeapNumberMaterializationDescriptor d = deferred_heap_numbers_[i]; 4228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Object> num = isolate_->factory()->NewNumber(d.value()); 4238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (FLAG_trace_deopt) { 4248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PrintF("Materializing a new heap number %p [%e] in slot %p\n", 4258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch reinterpret_cast<void*>(*num), 4268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch d.value(), 4278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch d.slot_address()); 4288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Memory::Object_at(d.slot_address()) = *num; 431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::DoTranslateCommand(TranslationIterator* iterator, 436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int frame_index, 437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned output_offset) { 438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch disasm::NameConverter converter; 439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A GC-safe temporary placeholder that we can put in the output frame. 440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const intptr_t kPlaceholder = reinterpret_cast<intptr_t>(Smi::FromInt(0)); 441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Ignore commands marked as duplicate and act on the first non-duplicate. 443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Translation::Opcode opcode = 444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<Translation::Opcode>(iterator->Next()); 445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (opcode == Translation::DUPLICATE) { 446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch opcode = static_cast<Translation::Opcode>(iterator->Next()); 447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch iterator->Skip(Translation::NumberOfOperandsFor(opcode)); 448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch opcode = static_cast<Translation::Opcode>(iterator->Next()); 449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (opcode) { 452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::BEGIN: 453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::FRAME: 454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::DUPLICATE: 455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::REGISTER: { 459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int input_reg = iterator->Next(); 460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch intptr_t input_value = input_->GetRegister(input_reg); 461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF( 463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch " 0x%08" V8PRIxPTR ": [top + %d] <- 0x%08" V8PRIxPTR " ; %s\n", 464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->GetTop() + output_offset, 465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset, 466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_value, 467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch converter.NameOfCPURegister(input_reg)); 468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->SetFrameSlot(output_offset, input_value); 470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::INT32_REGISTER: { 474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int input_reg = iterator->Next(); 475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch intptr_t value = input_->GetRegister(input_reg); 476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_smi = Smi::IsValid(value); 477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF( 479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch " 0x%08" V8PRIxPTR ": [top + %d] <- %" V8PRIdPTR " ; %s (%s)\n", 480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->GetTop() + output_offset, 481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset, 482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value, 483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch converter.NameOfCPURegister(input_reg), 484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch is_smi ? "smi" : "heap number"); 485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_smi) { 487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch intptr_t tagged_value = 488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value))); 489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->SetFrameSlot(output_offset, tagged_value); 490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We save the untagged value on the side and store a GC-safe 492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // temporary placeholder in the frame. 4938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddDoubleValue(output_[frame_index]->GetTop() + output_offset, 4948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static_cast<double>(static_cast<int32_t>(value))); 495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder); 496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::DOUBLE_REGISTER: { 501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int input_reg = iterator->Next(); 502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double value = input_->GetDoubleRegister(input_reg); 503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; %s\n", 505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->GetTop() + output_offset, 506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset, 507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value, 508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoubleRegister::AllocationIndexToString(input_reg)); 509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We save the untagged value on the side and store a GC-safe 511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // temporary placeholder in the frame. 5128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value); 513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder); 514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::STACK_SLOT: { 518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int input_slot_index = iterator->Next(); 519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned input_offset = 520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_->GetOffsetFromSlotIndex(this, input_slot_index); 521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch intptr_t input_value = input_->GetFrameSlot(input_offset); 522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" 0x%08" V8PRIxPTR ": ", 524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->GetTop() + output_offset); 525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[top + %d] <- 0x%08" V8PRIxPTR " ; [esp + %d]\n", 526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset, 527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_value, 528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_offset); 529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->SetFrameSlot(output_offset, input_value); 531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::INT32_STACK_SLOT: { 535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int input_slot_index = iterator->Next(); 536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned input_offset = 537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_->GetOffsetFromSlotIndex(this, input_slot_index); 538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch intptr_t value = input_->GetFrameSlot(input_offset); 539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_smi = Smi::IsValid(value); 540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" 0x%08" V8PRIxPTR ": ", 542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->GetTop() + output_offset); 543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("[top + %d] <- %" V8PRIdPTR " ; [esp + %d] (%s)\n", 544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset, 545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value, 546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_offset, 547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch is_smi ? "smi" : "heap number"); 548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_smi) { 550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch intptr_t tagged_value = 551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reinterpret_cast<intptr_t>(Smi::FromInt(static_cast<int>(value))); 552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->SetFrameSlot(output_offset, tagged_value); 553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We save the untagged value on the side and store a GC-safe 555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // temporary placeholder in the frame. 5568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddDoubleValue(output_[frame_index]->GetTop() + output_offset, 5578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static_cast<double>(static_cast<int32_t>(value))); 558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder); 559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::DOUBLE_STACK_SLOT: { 564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int input_slot_index = iterator->Next(); 565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned input_offset = 566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_->GetOffsetFromSlotIndex(this, input_slot_index); 567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double value = input_->GetDoubleFrameSlot(input_offset); 568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- %e ; [esp + %d]\n", 570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->GetTop() + output_offset, 571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset, 572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value, 573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_offset); 574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We save the untagged value on the side and store a GC-safe 576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // temporary placeholder in the frame. 5778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddDoubleValue(output_[frame_index]->GetTop() + output_offset, value); 578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->SetFrameSlot(output_offset, kPlaceholder); 579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::LITERAL: { 583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Object* literal = ComputeLiteral(iterator->Next()); 584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", 586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->GetTop() + output_offset, 587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset); 588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch literal->ShortPrint(); 589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" ; literal\n"); 590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch intptr_t value = reinterpret_cast<intptr_t>(literal); 592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->SetFrameSlot(output_offset, value); 593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::ARGUMENTS_OBJECT: { 597086aeeaae12517475c22695a200be45495516549Ben Murdoch // Use the arguments marker value as a sentinel and fill in the arguments 598086aeeaae12517475c22695a200be45495516549Ben Murdoch // object after the deoptimized frame is built. 599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(frame_index == 0); // Only supported for first frame. 600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_deopt) { 601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" 0x%08" V8PRIxPTR ": [top + %d] <- ", 602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->GetTop() + output_offset, 603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset); 60444f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->heap()->arguments_marker()->ShortPrint(); 605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" ; arguments object\n"); 606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 60744f0eee88ff00398ff7f715fab053374d808c90dSteve Block intptr_t value = reinterpret_cast<intptr_t>( 60844f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate_->heap()->arguments_marker()); 609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_[frame_index]->SetFrameSlot(output_offset, value); 610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool Deoptimizer::DoOsrTranslateCommand(TranslationIterator* iterator, 617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int* input_offset) { 618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch disasm::NameConverter converter; 619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FrameDescription* output = output_[0]; 620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The input values are all part of the unoptimized frame so they 622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // are all tagged pointers. 623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uintptr_t input_value = input_->GetFrameSlot(*input_offset); 624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Object* input_object = reinterpret_cast<Object*>(input_value); 625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Translation::Opcode opcode = 627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<Translation::Opcode>(iterator->Next()); 628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool duplicate = (opcode == Translation::DUPLICATE); 629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (duplicate) { 630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch opcode = static_cast<Translation::Opcode>(iterator->Next()); 631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (opcode) { 634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::BEGIN: 635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::FRAME: 636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::DUPLICATE: 637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); // Malformed input. 638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::REGISTER: { 641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int output_reg = iterator->Next(); 642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_osr) { 6431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" %s <- 0x%08" V8PRIxPTR " ; [sp + %d]\n", 644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch converter.NameOfCPURegister(output_reg), 645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_value, 646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *input_offset); 647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output->SetRegister(output_reg, input_value); 649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::INT32_REGISTER: { 653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Abort OSR if we don't have a number. 654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!input_object->IsNumber()) return false; 655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int output_reg = iterator->Next(); 657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int int32_value = input_object->IsSmi() 658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? Smi::cast(input_object)->value() 659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : FastD2I(input_object->Number()); 660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Abort the translation if the conversion lost information. 661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!input_object->IsSmi() && 662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FastI2D(int32_value) != input_object->Number()) { 663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_osr) { 664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("**** %g could not be converted to int32 ****\n", 665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_object->Number()); 666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_osr) { 6701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" %s <- %d (int32) ; [sp + %d]\n", 671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch converter.NameOfCPURegister(output_reg), 672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int32_value, 673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *input_offset); 674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output->SetRegister(output_reg, int32_value); 676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::DOUBLE_REGISTER: { 680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Abort OSR if we don't have a number. 681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!input_object->IsNumber()) return false; 682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int output_reg = iterator->Next(); 684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double double_value = input_object->Number(); 685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_osr) { 6861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" %s <- %g (double) ; [sp + %d]\n", 687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoubleRegister::AllocationIndexToString(output_reg), 688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double_value, 689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *input_offset); 690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output->SetDoubleRegister(output_reg, double_value); 692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::STACK_SLOT: { 696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int output_index = iterator->Next(); 697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned output_offset = 698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output->GetOffsetFromSlotIndex(this, output_index); 699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_osr) { 7001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" [sp + %d] <- 0x%08" V8PRIxPTR " ; [sp + %d]\n", 701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset, 702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_value, 703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *input_offset); 704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output->SetFrameSlot(output_offset, input_value); 706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::INT32_STACK_SLOT: { 710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Abort OSR if we don't have a number. 711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!input_object->IsNumber()) return false; 712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int output_index = iterator->Next(); 714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned output_offset = 715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output->GetOffsetFromSlotIndex(this, output_index); 716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int int32_value = input_object->IsSmi() 717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? Smi::cast(input_object)->value() 718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : DoubleToInt32(input_object->Number()); 719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Abort the translation if the conversion lost information. 720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!input_object->IsSmi() && 721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FastI2D(int32_value) != input_object->Number()) { 722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_osr) { 723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("**** %g could not be converted to int32 ****\n", 724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch input_object->Number()); 725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_osr) { 7291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" [sp + %d] <- %d (int32) ; [sp + %d]\n", 730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset, 731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int32_value, 732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *input_offset); 733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output->SetFrameSlot(output_offset, int32_value); 735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::DOUBLE_STACK_SLOT: { 739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const int kLowerOffset = 0 * kPointerSize; 740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const int kUpperOffset = 1 * kPointerSize; 741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Abort OSR if we don't have a number. 743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!input_object->IsNumber()) return false; 744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int output_index = iterator->Next(); 746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned output_offset = 747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output->GetOffsetFromSlotIndex(this, output_index); 748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double double_value = input_object->Number(); 749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint64_t int_value = BitCast<uint64_t, double>(double_value); 750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int32_t lower = static_cast<int32_t>(int_value); 751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int32_t upper = static_cast<int32_t>(int_value >> kBitsPerInt); 752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_osr) { 7531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" [sp + %d] <- 0x%08x (upper bits of %g) ; [sp + %d]\n", 754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset + kUpperOffset, 755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch upper, 756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double_value, 757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *input_offset); 7581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PrintF(" [sp + %d] <- 0x%08x (lower bits of %g) ; [sp + %d]\n", 759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output_offset + kLowerOffset, 760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lower, 761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double_value, 762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *input_offset); 763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output->SetFrameSlot(output_offset + kLowerOffset, lower); 765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch output->SetFrameSlot(output_offset + kUpperOffset, upper); 766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::LITERAL: { 770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Just ignore non-materialized literals. 771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch iterator->Next(); 772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Translation::ARGUMENTS_OBJECT: { 776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Optimized code assumes that the argument object has not been 777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // materialized and so bypasses it when doing arguments access. 778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We should have bailed out before starting the frame 779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // translation. 780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!duplicate) *input_offset -= kPointerSize; 786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Deoptimizer::PatchStackCheckCode(Code* unoptimized_code, 7911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* check_code, 7921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* replacement_code) { 7931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Iterate over the stack check table and patch every stack check 7941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // call to an unconditional call to the replacement code. 7951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(unoptimized_code->kind() == Code::FUNCTION); 7961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Address stack_check_cursor = unoptimized_code->instruction_start() + 7971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unoptimized_code->stack_check_table_offset(); 7981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block uint32_t table_length = Memory::uint32_at(stack_check_cursor); 7991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block stack_check_cursor += kIntSize; 8001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (uint32_t i = 0; i < table_length; ++i) { 8011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize); 8021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Address pc_after = unoptimized_code->instruction_start() + pc_offset; 8031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PatchStackCheckCodeAt(pc_after, check_code, replacement_code); 8041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block stack_check_cursor += 2 * kIntSize; 8051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 8061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 8071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid Deoptimizer::RevertStackCheckCode(Code* unoptimized_code, 8101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* check_code, 8111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Code* replacement_code) { 8121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Iterate over the stack check table and revert the patched 8131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // stack check calls. 8141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(unoptimized_code->kind() == Code::FUNCTION); 8151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Address stack_check_cursor = unoptimized_code->instruction_start() + 8161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block unoptimized_code->stack_check_table_offset(); 8171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block uint32_t table_length = Memory::uint32_at(stack_check_cursor); 8181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block stack_check_cursor += kIntSize; 8191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (uint32_t i = 0; i < table_length; ++i) { 8201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block uint32_t pc_offset = Memory::uint32_at(stack_check_cursor + kIntSize); 8211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Address pc_after = unoptimized_code->instruction_start() + pc_offset; 8221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block RevertStackCheckCodeAt(pc_after, check_code, replacement_code); 8231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block stack_check_cursor += 2 * kIntSize; 8241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 8251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 8261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 8271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned Deoptimizer::ComputeInputFrameSize() const { 829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned fixed_size = ComputeFixedSize(function_); 830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The fp-to-sp delta already takes the context and the function 831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // into account so we have to avoid double counting them (-2). 832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned result = fixed_size + fp_to_sp_delta_ - (2 * kPointerSize); 833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (bailout_type_ == OSR) { 835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(kasperl): It would be nice if we could verify that the 836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // size matches with the stack height we can compute based on the 837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // environment at the OSR entry. The code for that his built into 838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the DoComputeOsrOutputFrame function for now. 839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned stack_slots = optimized_code_->stack_slots(); 841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned outgoing_size = ComputeOutgoingArgumentSize(); 842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(result == fixed_size + (stack_slots * kPointerSize) + outgoing_size); 843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned Deoptimizer::ComputeFixedSize(JSFunction* function) const { 850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The fixed part of the frame consists of the return address, frame 851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // pointer, function, context, and all the incoming arguments. 852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static const unsigned kFixedSlotSize = 4 * kPointerSize; 853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return ComputeIncomingArgumentSize(function) + kFixedSlotSize; 854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned Deoptimizer::ComputeIncomingArgumentSize(JSFunction* function) const { 858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The incoming arguments is the values for formal parameters and 859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the receiver. Every slot contains a pointer. 860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned arguments = function->shared()->formal_parameter_count() + 1; 861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return arguments * kPointerSize; 862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned Deoptimizer::ComputeOutgoingArgumentSize() const { 866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizationInputData* data = DeoptimizationInputData::cast( 867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch optimized_code_->deoptimization_data()); 868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned height = data->ArgumentsStackHeight(bailout_id_)->value(); 869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return height * kPointerSize; 870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochObject* Deoptimizer::ComputeLiteral(int index) const { 874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizationInputData* data = DeoptimizationInputData::cast( 875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch optimized_code_->deoptimization_data()); 876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FixedArray* literals = data->LiteralArray(); 877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return literals->get(index); 878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid Deoptimizer::AddDoubleValue(intptr_t slot_address, 882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double value) { 8838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HeapNumberMaterializationDescriptor value_desc( 8848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch reinterpret_cast<Address>(slot_address), value); 8858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch deferred_heap_numbers_.Add(value_desc); 886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochLargeObjectChunk* Deoptimizer::CreateCode(BailoutType type) { 890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We cannot run this if the serializer is enabled because this will 891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // cause us to emit relocation information for the external 892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // references. This is fine because the deoptimizer's code section 893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // isn't meant to be serialized at all. 894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!Serializer::enabled()); 895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MacroAssembler masm(Isolate::Current(), NULL, 16 * KB); 89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm.set_emit_debug_code(false); 898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GenerateDeoptimizationEntries(&masm, kNumberOfEntries, type); 899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CodeDesc desc; 900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch masm.GetCode(&desc); 901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(desc.reloc_size == 0); 902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LargeObjectChunk* chunk = LargeObjectChunk::New(desc.instr_size, EXECUTABLE); 904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(chunk->GetStartAddress(), desc.buffer, desc.instr_size); 905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CPU::FlushICache(chunk->GetStartAddress(), desc.instr_size); 906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return chunk; 907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochCode* Deoptimizer::FindDeoptimizingCodeFromAddress(Address addr) { 91144f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizingCodeListNode* node = 91244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate::Current()->deoptimizer_data()->deoptimizing_code_list_; 913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (node != NULL) { 914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (node->code()->contains(addr)) return *node->code(); 915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch node = node->next(); 916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return NULL; 918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Deoptimizer::RemoveDeoptimizingCode(Code* code) { 92244f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizerData* data = Isolate::Current()->deoptimizer_data(); 92344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(data->deoptimizing_code_list_ != NULL); 924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Run through the code objects to find this one and remove it. 925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DeoptimizingCodeListNode* prev = NULL; 92644f0eee88ff00398ff7f715fab053374d808c90dSteve Block DeoptimizingCodeListNode* current = data->deoptimizing_code_list_; 927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (*current->code() == code) { 929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Unlink from list. If prev is NULL we are looking at the first element. 930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prev == NULL) { 93144f0eee88ff00398ff7f715fab053374d808c90dSteve Block data->deoptimizing_code_list_ = current->next(); 932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prev->set_next(current->next()); 934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch delete current; 936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Move to next in list. 939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prev = current; 940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Deoptimizing code is removed through weak callback. Each object is expected 943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // to be removed once and only once. 944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochFrameDescription::FrameDescription(uint32_t frame_size, 949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch JSFunction* function) 950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : frame_size_(frame_size), 951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function_(function), 952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch top_(kZapUint32), 953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pc_(kZapUint32), 954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch fp_(kZapUint32) { 955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Zap all the registers. 956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int r = 0; r < Register::kNumRegisters; r++) { 957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetRegister(r, kZapUint32); 958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Zap all the slots. 961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (unsigned o = 0; o < frame_size; o += kPointerSize) { 962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetFrameSlot(o, kZapUint32); 963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochunsigned FrameDescription::GetOffsetFromSlotIndex(Deoptimizer* deoptimizer, 968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int slot_index) { 969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (slot_index >= 0) { 970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Local or spill slots. Skip the fixed part of the frame 971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // including all arguments. 972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned base = static_cast<unsigned>( 973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch GetFrameSize() - deoptimizer->ComputeFixedSize(GetFunction())); 974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return base - ((slot_index + 1) * kPointerSize); 975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Incoming parameter. 977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch unsigned base = static_cast<unsigned>(GetFrameSize() - 978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch deoptimizer->ComputeIncomingArgumentSize(GetFunction())); 979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return base - ((slot_index + 1) * kPointerSize); 980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TranslationBuffer::Add(int32_t value) { 985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Encode the sign bit in the least significant bit. 986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_negative = (value < 0); 987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t bits = ((is_negative ? -value : value) << 1) | 988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int32_t>(is_negative); 989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Encode the individual bytes using the least significant bit of 990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // each byte to indicate whether or not more bytes follow. 991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { 992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t next = bits >> 7; 993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch contents_.Add(((bits << 1) & 0xFF) | (next != 0)); 994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bits = next; 995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (bits != 0); 996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint32_t TranslationIterator::Next() { 1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(HasNext()); 1001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Run through the bytes until we reach one with a least significant 1002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // bit of zero (marks the end). 1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t bits = 0; 1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; true; i += 7) { 1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint8_t next = buffer_->get(index_++); 1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bits |= (next >> 1) << i; 1007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ((next & 1) == 0) break; 1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The bits encode the sign in the least significant bit. 1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_negative = (bits & 1) == 1; 1011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int32_t result = bits >> 1; 1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return is_negative ? -result : result; 1013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHandle<ByteArray> TranslationBuffer::CreateByteArray() { 1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = contents_.length(); 101844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<ByteArray> result = 101944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate::Current()->factory()->NewByteArray(length, TENURED); 1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(result->GetDataStartAddress(), contents_.ToVector().start(), length); 1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::BeginFrame(int node_id, int literal_id, unsigned height) { 1026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(FRAME); 1027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(node_id); 1028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(literal_id); 1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(height); 1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreRegister(Register reg) { 1034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(REGISTER); 1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(reg.code()); 1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreInt32Register(Register reg) { 1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(INT32_REGISTER); 1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(reg.code()); 1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreDoubleRegister(DoubleRegister reg) { 1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(DOUBLE_REGISTER); 1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(DoubleRegister::ToAllocationIndex(reg)); 1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreStackSlot(int index) { 1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(STACK_SLOT); 1053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(index); 1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreInt32StackSlot(int index) { 1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(INT32_STACK_SLOT); 1059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(index); 1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreDoubleStackSlot(int index) { 1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(DOUBLE_STACK_SLOT); 1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(index); 1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreLiteral(int literal_id) { 1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(LITERAL); 1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(literal_id); 1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::StoreArgumentsObject() { 1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(ARGUMENTS_OBJECT); 1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid Translation::MarkDuplicate() { 1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch buffer_->Add(DUPLICATE); 1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint Translation::NumberOfOperandsFor(Opcode opcode) { 1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (opcode) { 1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ARGUMENTS_OBJECT: 1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case DUPLICATE: 1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 0; 1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case BEGIN: 1091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case REGISTER: 1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case INT32_REGISTER: 1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case DOUBLE_REGISTER: 1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case STACK_SLOT: 1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case INT32_STACK_SLOT: 1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case DOUBLE_STACK_SLOT: 1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case LITERAL: 1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 1; 1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case FRAME: 1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 3; 1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return -1; 1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef OBJECT_PRINT 1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* Translation::StringFor(Opcode opcode) { 1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (opcode) { 1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case BEGIN: 1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "BEGIN"; 1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case FRAME: 1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "FRAME"; 1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case REGISTER: 1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "REGISTER"; 1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case INT32_REGISTER: 1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "INT32_REGISTER"; 1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case DOUBLE_REGISTER: 1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "DOUBLE_REGISTER"; 1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case STACK_SLOT: 1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "STACK_SLOT"; 1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case INT32_STACK_SLOT: 1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "INT32_STACK_SLOT"; 1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case DOUBLE_STACK_SLOT: 1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "DOUBLE_STACK_SLOT"; 1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case LITERAL: 1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "LITERAL"; 1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ARGUMENTS_OBJECT: 1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "ARGUMENTS_OBJECT"; 1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case DUPLICATE: 1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return "DUPLICATE"; 1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return ""; 1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochDeoptimizingCodeListNode::DeoptimizingCodeListNode(Code* code): next_(NULL) { 114244f0eee88ff00398ff7f715fab053374d808c90dSteve Block GlobalHandles* global_handles = Isolate::Current()->global_handles(); 1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Globalize the code object and make it weak. 114444f0eee88ff00398ff7f715fab053374d808c90dSteve Block code_ = Handle<Code>::cast(global_handles->Create(code)); 114544f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->MakeWeak(reinterpret_cast<Object**>(code_.location()), 114644f0eee88ff00398ff7f715fab053374d808c90dSteve Block this, 114744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Deoptimizer::HandleWeakDeoptimizedCode); 1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochDeoptimizingCodeListNode::~DeoptimizingCodeListNode() { 115244f0eee88ff00398ff7f715fab053374d808c90dSteve Block GlobalHandles* global_handles = Isolate::Current()->global_handles(); 115344f0eee88ff00398ff7f715fab053374d808c90dSteve Block global_handles->Destroy(reinterpret_cast<Object**>(code_.location())); 1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 11578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// We can't intermix stack decoding and allocations because 11588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// deoptimization infrastracture is not GC safe. 11598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Thus we build a temporary structure in malloced space. 11608b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochSlotRef SlotRef::ComputeSlotForNextArgument(TranslationIterator* iterator, 11618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch DeoptimizationInputData* data, 11628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch JavaScriptFrame* frame) { 11638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Translation::Opcode opcode = 11648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static_cast<Translation::Opcode>(iterator->Next()); 11658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch switch (opcode) { 11678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::BEGIN: 11688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::FRAME: 11698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Peeled off before getting here. 11708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 11718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::ARGUMENTS_OBJECT: 11738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // This can be only emitted for local slots not for argument slots. 11748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 11758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::REGISTER: 11778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::INT32_REGISTER: 11788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::DOUBLE_REGISTER: 11798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::DUPLICATE: 11808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // We are at safepoint which corresponds to call. All registers are 11818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // saved by caller so there would be no live registers at this 11828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // point. Thus these translation commands should not be used. 11838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch break; 11848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::STACK_SLOT: { 11868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int slot_index = iterator->Next(); 11878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Address slot_addr = SlotAddress(frame, slot_index); 11888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return SlotRef(slot_addr, SlotRef::TAGGED); 11898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 11908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::INT32_STACK_SLOT: { 11928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int slot_index = iterator->Next(); 11938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Address slot_addr = SlotAddress(frame, slot_index); 11948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return SlotRef(slot_addr, SlotRef::INT32); 11958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 11968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 11978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::DOUBLE_STACK_SLOT: { 11988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int slot_index = iterator->Next(); 11998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Address slot_addr = SlotAddress(frame, slot_index); 12008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return SlotRef(slot_addr, SlotRef::DOUBLE); 12018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch case Translation::LITERAL: { 12048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int literal_index = iterator->Next(); 12058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return SlotRef(data->LiteralArray()->get(literal_index)); 12068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch UNREACHABLE(); 12108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return SlotRef(); 12118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 12128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid SlotRef::ComputeSlotMappingForArguments(JavaScriptFrame* frame, 12158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int inlined_frame_index, 12168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Vector<SlotRef>* args_slots) { 12178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AssertNoAllocation no_gc; 12188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int deopt_index = AstNode::kNoNumber; 12198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch DeoptimizationInputData* data = 12208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static_cast<OptimizedFrame*>(frame)->GetDeoptimizationData(&deopt_index); 12218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch TranslationIterator it(data->TranslationByteArray(), 12228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch data->TranslationIndex(deopt_index)->value()); 12238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next()); 12248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(opcode == Translation::BEGIN); 12258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int frame_count = it.Next(); 12268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch USE(frame_count); 12278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(frame_count > inlined_frame_index); 12288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int frames_to_skip = inlined_frame_index; 12298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch while (true) { 12308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch opcode = static_cast<Translation::Opcode>(it.Next()); 12318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Skip over operands to advance to the next opcode. 12328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch it.Skip(Translation::NumberOfOperandsFor(opcode)); 12338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (opcode == Translation::FRAME) { 12348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (frames_to_skip == 0) { 12358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // We reached the frame corresponding to the inlined function 12368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // in question. Process the translation commands for the 12378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // arguments. 12388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // 12398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Skip the translation command for the receiver. 12408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch it.Skip(Translation::NumberOfOperandsFor( 12418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static_cast<Translation::Opcode>(it.Next()))); 12428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Compute slots for arguments. 12438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (int i = 0; i < args_slots->length(); ++i) { 12448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch (*args_slots)[i] = ComputeSlotForNextArgument(&it, data, frame); 12458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return; 12478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch frames_to_skip--; 12498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 12518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch UNREACHABLE(); 12538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 12548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 12558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} } // namespace v8::internal 1257