13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Redistribution and use in source and binary forms, with or without 3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// modification, are permitted provided that the following conditions are 4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// met: 5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Redistributions of source code must retain the above copyright 7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// notice, this list of conditions and the following disclaimer. 8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Redistributions in binary form must reproduce the above 9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// copyright notice, this list of conditions and the following 10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// disclaimer in the documentation and/or other materials provided 11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// with the distribution. 12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Neither the name of Google Inc. nor the names of its 13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// contributors may be used to endorse or promote products derived 14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from this software without specific prior written permission. 15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2844f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "v8.h" 29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hydrogen.h" 30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "codegen.h" 32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h" 33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hashmap.h" 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "lithium-allocator.h" 35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "parser.h" 363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "scopeinfo.h" 37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "scopes.h" 381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block#include "stub-cache.h" 39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#if V8_TARGET_ARCH_IA32 41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "ia32/lithium-codegen-ia32.h" 42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#elif V8_TARGET_ARCH_X64 43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "x64/lithium-codegen-x64.h" 44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#elif V8_TARGET_ARCH_ARM 45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "arm/lithium-codegen-arm.h" 4644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#elif V8_TARGET_ARCH_MIPS 4744f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "mips/lithium-codegen-mips.h" 48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#else 49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#error Unsupported target architecture. 50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 { 53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal { 54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock::HBasicBlock(HGraph* graph) 56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : block_id_(graph->GetNextBlockID()), 57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_(graph), 58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_(4), 59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first_(NULL), 60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_(NULL), 61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch end_(NULL), 62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_information_(NULL), 63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch predecessors_(2), 64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_(NULL), 65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominated_blocks_(4), 66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_environment_(NULL), 67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch argument_count_(-1), 68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first_instruction_index_(-1), 69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_instruction_index_(-1), 70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch deleted_phis_(4), 711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block parent_loop_header_(NULL), 723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch is_inline_return_target_(false), 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch is_deoptimizing_(false), 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dominates_loop_successors_(false) { } 75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AttachLoopInformation() { 78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsLoopHeader()); 798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch loop_information_ = new(zone()) HLoopInformation(this); 80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::DetachLoopInformation() { 84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsLoopHeader()); 85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_information_ = NULL; 86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddPhi(HPhi* phi) { 90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsStartBlock()); 91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_.Add(phi); 92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->SetBlock(this); 93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RemovePhi(HPhi* phi) { 97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->block() == this); 98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phis_.Contains(phi)); 9944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(phi->HasNoUses() || !phi->is_live()); 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch phi->Kill(); 101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_.RemoveElement(phi); 102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->SetBlock(NULL); 103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddInstruction(HInstruction* instr) { 107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsStartBlock() || !IsFinished()); 108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!instr->IsLinked()); 109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsFinished()); 110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first_ == NULL) { 1118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HBlockEntry* entry = new(zone()) HBlockEntry(); 112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch entry->InitializeAsFirst(this); 113e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch first_ = last_ = entry; 114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch instr->InsertAfter(last_); 116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch last_ = instr; 117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHDeoptimize* HBasicBlock::CreateDeoptimize( 121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HDeoptimize::UseEnvironment has_uses) { 12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(HasEnvironment()); 123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (has_uses == HDeoptimize::kNoUses) return new(zone()) HDeoptimize(0); 12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HEnvironment* environment = last_environment(); 1268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HDeoptimize* instr = new(zone()) HDeoptimize(environment->length()); 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < environment->length(); i++) { 12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* val = environment->values()->at(i); 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block instr->AddEnvironmentValue(val); 13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block return instr; 13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 13444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1363fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHSimulate* HBasicBlock::CreateSimulate(int ast_id) { 137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(HasEnvironment()); 138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* environment = last_environment(); 1393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ast_id == AstNode::kNoNumber || 1403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch environment->closure()->shared()->VerifyBailoutId(ast_id)); 141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int push_count = environment->push_count(); 143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int pop_count = environment->pop_count(); 144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HSimulate* instr = new(zone()) HSimulate(ast_id, pop_count); 146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = push_count - 1; i >= 0; --i) { 147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->AddPushedValue(environment->ExpressionStackAt(i)); 148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < environment->assigned_variables()->length(); ++i) { 150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = environment->assigned_variables()->at(i); 151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->AddAssignedValue(index, environment->Lookup(index)); 152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment->ClearHistory(); 154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Finish(HControlInstruction* end) { 159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsFinished()); 160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(end); 161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch end_ = end; 1623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch it.Current()->RegisterPredecessor(this); 164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) { 16944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (block->IsInlineReturnTarget()) { 1708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HLeaveInlined); 1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch last_environment_ = last_environment()->DiscardInlined(drop_extra); 17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(AstNode::kNoNumber); 1748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGoto* instr = new(zone()) HGoto(block); 175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Finish(instr); 176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HBasicBlock::AddLeaveInlined(HValue* return_value, 1803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* target, 1813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool drop_extra) { 18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(target->IsInlineReturnTarget()); 18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(return_value != NULL); 1848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HLeaveInlined); 1853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch last_environment_ = last_environment()->DiscardInlined(drop_extra); 18644f0eee88ff00398ff7f715fab053374d808c90dSteve Block last_environment()->Push(return_value); 18744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddSimulate(AstNode::kNoNumber); 1888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGoto* instr = new(zone()) HGoto(target); 18944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Finish(instr); 19044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 19144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 19244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!HasEnvironment()); 195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(first() == NULL); 196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UpdateEnvironment(env); 197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HBasicBlock::SetJoinId(int ast_id) { 201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = predecessors_.length(); 202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(length > 0); 203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; i++) { 204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* predecessor = predecessors_[i]; 205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(predecessor->end()->IsGoto()); 206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HSimulate* simulate = HSimulate::cast(predecessor->end()->previous()); 207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We only need to verify the ID once. 208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(i != 0 || 209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch predecessor->last_environment()->closure()->shared() 2103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ->VerifyBailoutId(ast_id)); 2113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch simulate->set_ast_id(ast_id); 212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HBasicBlock::Dominates(HBasicBlock* other) const { 217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* current = other->dominator(); 218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current == this) return true; 220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->dominator(); 221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochint HBasicBlock::LoopNestingDepth() const { 227589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch const HBasicBlock* current = this; 228589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int result = (current->IsLoopHeader()) ? 1 : 0; 229589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch while (current->parent_loop_header() != NULL) { 230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch current = current->parent_loop_header(); 231589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch result++; 232589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 233589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return result; 234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) { 238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsLoopHeader()); 239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetJoinId(stmt->EntryId()); 241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (predecessors()->length() == 1) { 242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // This is a degenerated loop. 243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DetachLoopInformation(); 244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only the first entry into the loop is from outside the loop. All other 248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // entries must be back edges. 249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 1; i < predecessors()->length(); ++i) { 250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_information()->RegisterBackEdge(predecessors()->at(i)); 251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { 256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasPredecessor()) { 257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only loop header blocks can have a predecessor added after 258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // instructions have been added to the block (they have phis for all 259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // values in the environment, these phis may be eliminated later). 260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsLoopHeader() || first_ == NULL); 261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* incoming_env = pred->last_environment(); 262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (IsLoopHeader()) { 2639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(phis()->length() == incoming_env->length()); 264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phis_.length(); ++i) { 265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_[i]->AddInput(incoming_env->values()->at(i)); 266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_environment()->AddIncomingEdge(this, pred->last_environment()); 269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (!HasEnvironment() && !IsFinished()) { 271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsLoopHeader()); 272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetInitialEnvironment(pred->last_environment()->Copy()); 273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch predecessors_.Add(pred); 276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddDominatedBlock(HBasicBlock* block) { 280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!dominated_blocks_.Contains(block)); 281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keep the list of dominated blocks sorted such that if there is two 282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // succeeding block in this list, the predecessor is before the successor. 283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = 0; 284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (index < dominated_blocks_.length() && 285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominated_blocks_[index]->block_id() < block->block_id()) { 286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ++index; 287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominated_blocks_.InsertAt(index, block); 289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AssignCommonDominator(HBasicBlock* other) { 293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (dominator_ == NULL) { 294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_ = other; 295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->AddDominatedBlock(this); 296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (other->dominator() != NULL) { 297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* first = dominator_; 298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* second = other; 299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (first != second) { 301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first->block_id() > second->block_id()) { 302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first = first->dominator(); 303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch second = second->dominator(); 305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(first != NULL && second != NULL); 307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (dominator_ != first) { 310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(dominator_->dominated_blocks_.Contains(this)); 311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_->dominated_blocks_.RemoveElement(this); 312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_ = first; 313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first->AddDominatedBlock(this); 314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HBasicBlock::AssignLoopSuccessorDominators() { 3203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Mark blocks that dominate all subsequent reachable blocks inside their 3213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // loop. Exploit the fact that blocks are sorted in reverse post order. When 3223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the loop is visited in increasing block id order, if the number of 3233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // non-loop-exiting successor edges at the dominator_candidate block doesn't 3243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // exceed the number of previously encountered predecessor edges, there is no 3253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // path from the loop header to any block with higher id that doesn't go 3263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // through the dominator_candidate block. In this case, the 3273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // dominator_candidate block is guaranteed to dominate all blocks reachable 3283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // from it with higher ids. 3293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* last = loop_information()->GetLastBackEdge(); 3303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int outstanding_successors = 1; // one edge from the pre-header 3313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Header always dominates everything. 3323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MarkAsLoopSuccessorDominator(); 3333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int j = block_id(); j <= last->block_id(); ++j) { 3343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* dominator_candidate = graph_->blocks()->at(j); 3353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (HPredecessorIterator it(dominator_candidate); !it.Done(); 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch it.Advance()) { 3373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* predecessor = it.Current(); 3383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Don't count back edges. 3393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (predecessor->block_id() < dominator_candidate->block_id()) { 3403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch outstanding_successors--; 3413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If more successors than predecessors have been seen in the loop up to 3453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // now, it's not possible to guarantee that the current block dominates 3463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // all of the blocks with higher IDs. In this case, assume conservatively 3473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // that those paths through loop that don't go through the current block 3483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // contain all of the loop's dependencies. Also be careful to record 3493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // dominator information about the current loop that's being processed, 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // and not nested loops, which will be processed when 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // AssignLoopSuccessorDominators gets called on their header. 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(outstanding_successors >= 0); 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header(); 3543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (outstanding_successors == 0 && 3553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) { 3563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dominator_candidate->MarkAsLoopSuccessorDominator(); 3573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HControlInstruction* end = dominator_candidate->end(); 3593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 3603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* successor = it.Current(); 3613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Only count successors that remain inside the loop and don't loop back 3623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // to a loop header. 3633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (successor->block_id() > dominator_candidate->block_id() && 3643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch successor->block_id() <= last->block_id()) { 3653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Backwards edges must land on loop headers. 3663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(successor->block_id() > dominator_candidate->block_id() || 3673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch successor->IsLoopHeader()); 3683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch outstanding_successors++; 3693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const { 376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < predecessors_.length(); ++i) { 377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (predecessors_[i] == predecessor) return i; 378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return -1; 381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Verify() { 386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that every block is finished. 387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsFinished()); 388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(block_id() >= 0); 38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 39044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the incoming edges are in edge split form. 39144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (predecessors_.length() > 1) { 39244f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < predecessors_.length(); ++i) { 39344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(predecessors_[i]->end()->SecondSuccessor() == NULL); 39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::RegisterBackEdge(HBasicBlock* block) { 401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch this->back_edges_.Add(block); 402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddBlock(block); 403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HLoopInformation::GetLastBackEdge() const { 407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int max_id = -1; 408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* result = NULL; 409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < back_edges_.length(); ++i) { 410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* cur = back_edges_[i]; 411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (cur->block_id() > max_id) { 412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch max_id = cur->block_id(); 413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = cur; 414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::AddBlock(HBasicBlock* block) { 421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block == loop_header()) return; 422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->parent_loop_header() == loop_header()) return; 423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->parent_loop_header() != NULL) { 424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddBlock(block->parent_loop_header()); 425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->set_parent_loop_header(loop_header()); 427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.Add(block); 428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < block->predecessors()->length(); ++i) { 429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddBlock(block->predecessors()->at(i)); 430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Checks reachability of the blocks in this graph and stores a bit in 438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the BitVector "reachable()" for every block that can be reached 439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from the start block of the graph. If "dont_visit" is non-null, the given 440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// block is treated as if it would not be part of the graph. "visited_count()" 441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// returns the number of reachable blocks. 442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass ReachabilityAnalyzer BASE_EMBEDDED { 443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ReachabilityAnalyzer(HBasicBlock* entry_block, 445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int block_count, 446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dont_visit) 447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : visited_count_(0), 448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stack_(16), 4493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reachable_(block_count, ZONE), 450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dont_visit_(dont_visit) { 451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushBlock(entry_block); 452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Analyze(); 453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int visited_count() const { return visited_count_; } 456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const BitVector* reachable() const { return &reachable_; } 457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PushBlock(HBasicBlock* block) { 460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block != NULL && block != dont_visit_ && 461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !reachable_.Contains(block->block_id())) { 462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reachable_.Add(block->block_id()); 463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stack_.Add(block); 464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visited_count_++; 465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze() { 469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!stack_.is_empty()) { 470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HControlInstruction* end = stack_.RemoveLast()->end(); 4713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 4723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PushBlock(it.Current()); 4733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int visited_count_; 478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*> stack_; 479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector reachable_; 480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dont_visit_; 481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraph::Verify(bool do_full_verify) const { 485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); i++) { 486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = blocks_.at(i); 487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->Verify(); 489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that every block contains at least one node and that only the last 491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // node is a control instruction. 492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = block->first(); 493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current != NULL && current->IsBlockEntry()); 494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT((current->next() == NULL) == current->IsControlInstruction()); 496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current->block() == block); 497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->Verify(); 498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that successors are correctly set. 502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* first = block->end()->FirstSuccessor(); 503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* second = block->end()->SecondSuccessor(); 504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(second == NULL || first != NULL); 505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that the predecessor array is correct. 507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first != NULL) { 508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(first->predecessors()->Contains(block)); 509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (second != NULL) { 510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(second->predecessors()->Contains(block)); 511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that phis have correct arguments. 515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < block->phis()->length(); j++) { 516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = block->phis()->at(j); 517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->Verify(); 518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that all join blocks have predecessors that end with an 521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // unconditional goto and agree on their environment node id. 522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->predecessors()->length() >= 2) { 523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int id = block->predecessors()->first()->last_environment()->ast_id(); 524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int k = 0; k < block->predecessors()->length(); k++) { 525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* predecessor = block->predecessors()->at(k); 526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(predecessor->end()->IsGoto()); 527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(predecessor->last_environment()->ast_id() == id); 528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check special property of first block to have no predecessors. 533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(blocks_.at(0)->predecessors()->is_empty()); 534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (do_full_verify) { 5363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the graph is fully connected. 5373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL); 5383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(analyzer.visited_count() == blocks_.length()); 539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that entry block dominator is NULL. 5413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(entry_block_->dominator() == NULL); 542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check dominators. 5443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < blocks_.length(); ++i) { 5453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* block = blocks_.at(i); 5463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (block->dominator() == NULL) { 5473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Only start block may have no dominator assigned to. 5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(i == 0); 5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Assert that block is unreachable if dominator must not be visited. 5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ReachabilityAnalyzer dominator_analyzer(entry_block_, 5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch blocks_.length(), 5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch block->dominator()); 5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id())); 5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, 564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Object* value) { 565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!pointer->is_set()) { 5668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HConstant* constant = new(zone()) HConstant(Handle<Object>(value), 5678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Representation::Tagged()); 568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch constant->InsertAfter(GetConstantUndefined()); 569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pointer->set(constant); 570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return pointer->get(); 572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant1() { 576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return GetConstant(&constant_1_, Smi::FromInt(1)); 577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantMinus1() { 581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return GetConstant(&constant_minus1_, Smi::FromInt(-1)); 582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantTrue() { 58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetConstant(&constant_true_, isolate()->heap()->true_value()); 587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantFalse() { 59144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetConstant(&constant_false_, isolate()->heap()->false_value()); 592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5953fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHConstant* HGraph::GetConstantHole() { 5963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return GetConstant(&constant_hole_, isolate()->heap()->the_hole_value()); 5973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 5983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHGraphBuilder::HGraphBuilder(CompilationInfo* info, 601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TypeFeedbackOracle* oracle) 602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : function_state_(NULL), 6033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch initial_function_state_(this, info, oracle, NORMAL_RETURN), 604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ast_context_(NULL), 605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break_scope_(NULL), 606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch graph_(NULL), 607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current_block_(NULL), 608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inlined_count_(0), 609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch zone_(info->isolate()->zone()), 610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inline_bailout_(false) { 611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This is not initialized in the initializer list because the 612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // constructor for the initial state relies on function_state_ == NULL 613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // to know it's the initial state. 614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch function_state_= &initial_function_state_; 615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first, 618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* second, 619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int join_id) { 620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (first == NULL) { 621e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return second; 622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (second == NULL) { 623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return first; 624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 625e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* join_block = graph_->CreateBasicBlock(); 626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch first->Goto(join_block); 627e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch second->Goto(join_block); 628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch join_block->SetJoinId(join_id); 629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return join_block; 630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement, 635e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* exit_block, 636e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* continue_block) { 637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (continue_block != NULL) { 638e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (exit_block != NULL) exit_block->Goto(continue_block); 639e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch continue_block->SetJoinId(statement->ContinueId()); 640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return continue_block; 641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 642e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return exit_block; 643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement, 647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_entry, 648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_exit, 649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_successor, 650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* break_block) { 6513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (body_exit != NULL) body_exit->Goto(loop_entry); 652e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_entry->PostProcessLoopHeader(statement); 653e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (break_block != NULL) { 654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (loop_successor != NULL) loop_successor->Goto(break_block); 655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break_block->SetJoinId(statement->ExitId()); 656e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return break_block; 657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return loop_successor; 659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HBasicBlock::FinishExit(HControlInstruction* instruction) { 663e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Finish(instruction); 664e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ClearEnvironment(); 665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHGraph::HGraph(CompilationInfo* info) 66944f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(info->isolate()), 670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next_block_id_(0), 67144f0eee88ff00398ff7f715fab053374d808c90dSteve Block entry_block_(NULL), 672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_(8), 673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_(16), 674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi_list_(NULL) { 6758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch start_environment_ = 6768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HEnvironment(NULL, info->scope(), info->closure()); 6778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch start_environment_->set_ast_id(AstNode::kFunctionEntryId); 67844f0eee88ff00398ff7f715fab053374d808c90dSteve Block entry_block_ = CreateBasicBlock(); 67944f0eee88ff00398ff7f715fab053374d808c90dSteve Block entry_block_->SetInitialEnvironment(start_environment_); 680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHandle<Code> HGraph::Compile(CompilationInfo* info) { 684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int values = GetMaximumValueID(); 6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (values > LUnallocated::kMaxVirtualRegisters) { 6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_bailout) { 6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("Not enough virtual registers for (values).\n"); 6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Handle<Code>::null(); 690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LAllocator allocator(values, this); 692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LChunkBuilder builder(info, this, &allocator); 693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LChunk* chunk = builder.Build(); 694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk == NULL) return Handle<Code>::null(); 695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!allocator.Allocate(chunk)) { 6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_bailout) { 6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("Not enough virtual registers (regalloc).\n"); 6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MacroAssembler assembler(info->isolate(), NULL, 0); 704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LCodeGen generator(chunk, &assembler, info); 705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch chunk->MarkEmptyBlocks(); 707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (generator.GenerateCode()) { 709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_codegen) { 710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Crankshaft Compiler - "); 711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CodeGenerator::MakeCodePrologue(info); 713589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Code::Flags flags = Code::ComputeFlags(Code::OPTIMIZED_FUNCTION); 714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Code> code = 715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CodeGenerator::MakeCodeEpilogue(&assembler, flags, info); 716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch generator.FinishCode(code); 717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CodeGenerator::PrintCode(code, info); 718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return code; 719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Handle<Code>::null(); 721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraph::CreateBasicBlock() { 7258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HBasicBlock* result = new(zone()) HBasicBlock(this); 726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.Add(result); 727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Canonicalize() { 732e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!FLAG_use_canonicalizing) return; 7333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Canonicalize", this); 734e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < blocks()->length(); ++i) { 735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HInstruction* instr = blocks()->at(i)->first(); 736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (instr != NULL) { 737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HValue* value = instr->Canonicalize(); 738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (value != instr) instr->DeleteAndReplaceWith(value); 739e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch instr = instr->next(); 740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::OrderBlocks() { 7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Block ordering"); 7473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BitVector visited(blocks_.length(), zone()); 748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*> reverse_result(8); 750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* start = blocks_[0]; 751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(start, &visited, &reverse_result, NULL); 752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block blocks_.Rewind(0); 754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = 0; 755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = reverse_result.length() - 1; i >= 0; --i) { 756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* b = reverse_result[i]; 757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.Add(b); 758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch b->set_block_id(index++); 759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PostorderLoopBlocks(HLoopInformation* loop, 764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector* visited, 765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*>* order, 766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header) { 767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < loop->blocks()->length(); ++i) { 768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* b = loop->blocks()->at(i); 7693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (HSuccessorIterator it(b->end()); !it.Done(); it.Advance()) { 7703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Postorder(it.Current(), visited, order, loop_header); 7713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (b->IsLoopHeader() && b != loop->loop_header()) { 773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PostorderLoopBlocks(b->loop_information(), visited, order, loop_header); 774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Postorder(HBasicBlock* block, 780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector* visited, 781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*>* order, 782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header) { 783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block == NULL || visited->Contains(block->block_id())) return; 784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->parent_loop_header() != loop_header) return; 785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visited->Add(block->block_id()); 786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PostorderLoopBlocks(block->loop_information(), visited, order, loop_header); 7883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { 7893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Postorder(it.Current(), visited, order, block); 7903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 7923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(block->IsFinished()); 7933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (HSuccessorIterator it(block->end()); !it.Done(); it.Advance()) { 7943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Postorder(it.Current(), visited, order, loop_header); 7953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(block->end()->FirstSuccessor() == NULL || 798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch order->Contains(block->end()->FirstSuccessor()) || 799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->end()->FirstSuccessor()->IsLoopHeader()); 800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(block->end()->SecondSuccessor() == NULL || 801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch order->Contains(block->end()->SecondSuccessor()) || 802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->end()->SecondSuccessor()->IsLoopHeader()); 803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch order->Add(block); 804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::AssignDominators() { 8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Assign dominators", this); 809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* block = blocks_[i]; 8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (block->IsLoopHeader()) { 81269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Only the first predecessor of a loop header is from outside the loop. 81369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // All others are back edges, and thus cannot dominate the loop header. 8143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch block->AssignCommonDominator(block->predecessors()->first()); 8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch block->AssignLoopSuccessorDominators(); 816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) { 818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); 819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 82269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch} 8233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 82469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// Mark all blocks that are dominated by an unconditional soft deoptimize to 82569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch// prevent code motion across those blocks. 82669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid HGraph::PropagateDeoptimizingMark() { 8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Propagate deoptimizing mark", this); 8283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MarkAsDeoptimizingRecursively(entry_block()); 829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraph::MarkAsDeoptimizingRecursively(HBasicBlock* block) { 8323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < block->dominated_blocks()->length(); ++i) { 8333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* dominated = block->dominated_blocks()->at(i); 8343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (block->IsDeoptimizing()) dominated->MarkAsDeoptimizing(); 8353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MarkAsDeoptimizingRecursively(dominated); 8363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 8373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 8383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::EliminateRedundantPhis() { 8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Redundant phi elimination", this); 841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Worklist of phis that can potentially be eliminated. Initialized with 843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // all phi nodes. When elimination of a phi node modifies another phi node 844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the modified phi node is added to the worklist. 845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HPhi*> worklist(blocks_.length()); 846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist.AddAll(*blocks_[i]->phis()); 848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!worklist.is_empty()) { 851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = worklist.RemoveLast(); 852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = phi->block(); 853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Skip phi node if it was already replaced. 855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block == NULL) continue; 856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get replacement value if phi is redundant. 858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* replacement = phi->GetRedundantReplacement(); 859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (replacement != NULL) { 861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Iterate through the uses and replace them all. 862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { 863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = it.value(); 864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value->SetOperandAt(it.index(), replacement); 865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (value->IsPhi()) worklist.Add(HPhi::cast(value)); 866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->RemovePhi(phi); 86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 87244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 87344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HGraph::EliminateUnreachablePhis() { 8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Unreachable phi elimination", this); 87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Initialize worklist. 87744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZoneList<HPhi*> phi_list(blocks_.length()); 87844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZoneList<HPhi*> worklist(blocks_.length()); 87944f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < blocks_.length(); ++i) { 88044f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int j = 0; j < blocks_[i]->phis()->length(); j++) { 88144f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhi* phi = blocks_[i]->phis()->at(j); 88244f0eee88ff00398ff7f715fab053374d808c90dSteve Block phi_list.Add(phi); 8831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We can't eliminate phis in the receiver position in the environment 8841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // because in case of throwing an error we need this value to 8851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // construct a stack trace. 88644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (phi->HasRealUses() || phi->IsReceiver()) { 88744f0eee88ff00398ff7f715fab053374d808c90dSteve Block phi->set_is_live(true); 88844f0eee88ff00398ff7f715fab053374d808c90dSteve Block worklist.Add(phi); 88944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 89044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 89144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 89244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 89344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Iteratively mark live phis. 89444f0eee88ff00398ff7f715fab053374d808c90dSteve Block while (!worklist.is_empty()) { 89544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhi* phi = worklist.RemoveLast(); 89644f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < phi->OperandCount(); i++) { 89744f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* operand = phi->OperandAt(i); 89844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (operand->IsPhi() && !HPhi::cast(operand)->is_live()) { 89944f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhi::cast(operand)->set_is_live(true); 90044f0eee88ff00398ff7f715fab053374d808c90dSteve Block worklist.Add(HPhi::cast(operand)); 90144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 90244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 90344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 90444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 90544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Remove unreachable phis. 90644f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < phi_list.length(); i++) { 90744f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhi* phi = phi_list[i]; 90844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!phi->is_live()) { 90944f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* block = phi->block(); 910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->RemovePhi(phi); 911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->RecordDeletedPhi(phi->merged_index()); 912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraph::CheckArgumentsPhiUses() { 918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int block_count = blocks_.length(); 919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < block_count; ++i) { 920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HPhi* phi = blocks_[i]->phis()->at(j); 922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We don't support phi uses of arguments for now. 923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (phi->CheckFlag(HValue::kIsArguments)) return false; 924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 9303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraph::CheckConstPhiUses() { 9313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int block_count = blocks_.length(); 9323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < block_count; ++i) { 9333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 9343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HPhi* phi = blocks_[i]->phis()->at(j); 9353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check for the hole value (from an uninitialized const). 9363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int k = 0; k < phi->OperandCount(); k++) { 9373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (phi->OperandAt(k) == GetConstantHole()) return false; 9383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 9393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 9403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 9413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return true; 9423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 9433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 9453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraph::CollectPhis() { 9463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int block_count = blocks_.length(); 9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch phi_list_ = new ZoneList<HPhi*>(block_count); 9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < block_count; ++i) { 9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhi* phi = blocks_[i]->phis()->at(j); 9513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch phi_list_->Add(phi); 9523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 9553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InferTypes(ZoneList<HValue*>* worklist) { 9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BitVector in_worklist(GetMaximumValueID(), zone()); 959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < worklist->length(); ++i) { 960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!in_worklist.Contains(worklist->at(i)->id())); 961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist.Add(worklist->at(i)->id()); 962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!worklist->is_empty()) { 965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* current = worklist->RemoveLast(); 966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist.Remove(current->id()); 967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->UpdateInferredType()) { 968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (HUseIterator it(current->uses()); !it.Done(); it.Advance()) { 969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* use = it.value(); 970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!in_worklist.Contains(use->id())) { 971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist.Add(use->id()); 972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist->Add(use); 973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HRangeAnalysis BASE_EMBEDDED { 981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch explicit HRangeAnalysis(HGraph* graph) : 9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch graph_(graph), zone_(graph->isolate()->zone()), changed_ranges_(16) { } 984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(); 986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void TraceRange(const char* msg, ...); 989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(HBasicBlock* block); 9903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void InferControlFlowRange(HCompareIDAndBranch* test, HBasicBlock* dest); 9913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void UpdateControlFlowRange(Token::Value op, HValue* value, HValue* other); 992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferRange(HValue* value); 993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void RollBackTo(int index); 994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AddRange(HValue* value, Range* range); 995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 9973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Zone* zone_; 998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> changed_ranges_; 999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::TraceRange(const char* msg, ...) { 1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_range) { 1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_list arguments; 1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_start(arguments, msg); 1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch OS::VPrint(msg, arguments); 1007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_end(arguments); 1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze() { 10133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Range analysis", graph_); 10143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Analyze(graph_->entry_block()); 1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze(HBasicBlock* block) { 1019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Analyzing block B%d\n", block->block_id()); 1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_changed_range = changed_ranges_.length() - 1; 1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Infer range based on control flow. 1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->predecessors()->length() == 1) { 1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* pred = block->predecessors()->first(); 10263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (pred->end()->IsCompareIDAndBranch()) { 10273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch InferControlFlowRange(HCompareIDAndBranch::cast(pred->end()), block); 1028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Process phi instructions. 1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < block->phis()->length(); ++i) { 1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = block->phis()->at(i); 10343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch InferRange(phi); 1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Go through all instructions of the current block. 1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != block->end()) { 1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferRange(instr); 1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Continue analysis in all dominated blocks. 1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < block->dominated_blocks()->length(); ++i) { 1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Analyze(block->dominated_blocks()->at(i)); 1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RollBackTo(last_changed_range); 1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 10533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HRangeAnalysis::InferControlFlowRange(HCompareIDAndBranch* test, 10543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* dest) { 10551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); 10563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (test->GetInputRepresentation().IsInteger32()) { 10573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Token::Value op = test->token(); 10583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (test->SecondSuccessor() == dest) { 10593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch op = Token::NegateCompareOp(op); 1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 10613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Token::Value inverted_op = Token::InvertCompareOp(op); 10623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch UpdateControlFlowRange(op, test->left(), test->right()); 10633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch UpdateControlFlowRange(inverted_op, test->right(), test->left()); 1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// We know that value [op] other. Use this information to update the range on 1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// value. 10703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HRangeAnalysis::UpdateControlFlowRange(Token::Value op, 10713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* value, 10723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* other) { 1073e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Range temp_range; 1074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Range* range = other->range() != NULL ? other->range() : &temp_range; 1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* new_range = NULL; 1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Control flow range infer %d %s %d\n", 1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->id(), 1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Name(op), 1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->id()); 1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::EQ || op == Token::EQ_STRICT) { 1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The same range has to apply for value. 10843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new_range = range->Copy(zone_); 1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::LT || op == Token::LTE) { 10863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new_range = range->CopyClearLower(zone_); 1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::LT) { 1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->AddConstant(-1); 1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::GT || op == Token::GTE) { 10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new_range = range->CopyClearUpper(zone_); 1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::GT) { 1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->AddConstant(1); 1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (new_range != NULL && !new_range->IsMostGeneric()) { 1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddRange(value, new_range); 1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferRange(HValue* value) { 1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!value->HasRange()); 1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!value->representation().IsNone()) { 11063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value->ComputeInitialRange(zone_); 1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* range = value->range(); 1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n", 1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->id(), 1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->Mnemonic(), 1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->lower(), 1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->upper()); 1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::RollBackTo(int index) { 1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = index + 1; i < changed_ranges_.length(); ++i) { 1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch changed_ranges_[i]->RemoveLastAddedRange(); 1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch changed_ranges_.Rewind(index + 1); 1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::AddRange(HValue* value, Range* range) { 1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* original_range = value->range(); 11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value->AddNewRange(range, zone_); 1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch changed_ranges_.Add(value); 1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* new_range = value->range(); 1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Updated range of %d set to [%d,%d]\n", 1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->id(), 1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->lower(), 1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->upper()); 1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (original_range != NULL) { 1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Original range was [%d,%d]\n", 1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch original_range->lower(), 1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch original_range->upper()); 1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("New information was [%d,%d]\n", 1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->lower(), 1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->upper()); 1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TraceGVN(const char* msg, ...) { 1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_gvn) { 1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_list arguments; 1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_start(arguments, msg); 1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch OS::VPrint(msg, arguments); 1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_end(arguments); 1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHValueMap::HValueMap(Zone* zone, const HValueMap* other) 1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : array_size_(other->array_size_), 1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_size_(other->lists_size_), 1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_(other->count_), 1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch present_flags_(other->present_flags_), 1160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch array_(zone->NewArray<HValueMapListElement>(other->array_size_)), 1161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch lists_(zone->NewArray<HValueMapListElement>(other->lists_size_)), 1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_(other->free_list_head_) { 1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement)); 1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement)); 1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 11683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HValueMap::Kill(GVNFlagSet flags) { 11693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(flags); 11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!present_flags_.ContainsAnyOf(depends_flags)) return; 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch present_flags_.RemoveAll(); 1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < array_size_; ++i) { 1173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = array_[i].value; 1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != NULL) { 1175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Clear list of collisions first, so we know if it becomes empty. 1176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int kept = kNil; // List of kept elements. 1177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next; 1178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int current = array_[i].next; current != kNil; current = next) { 1179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next = lists_[current].next; 11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* value = lists_[current].value; 11813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (value->gvn_flags().ContainsAnyOf(depends_flags)) { 1182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop it. 1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_--; 1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[current].next = free_list_head_; 1185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = current; 1186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keep it. 1188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[current].next = kept; 1189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch kept = current; 11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch present_flags_.Add(value->gvn_flags()); 1191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].next = kept; 1194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Now possibly drop directly indexed element. 11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = array_[i].value; 11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (value->gvn_flags().ContainsAnyOf(depends_flags)) { // Drop it. 1198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_--; 1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int head = array_[i].next; 1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (head == kNil) { 1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].value = NULL; 1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].value = lists_[head].value; 1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].next = lists_[head].next; 1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[head].next = free_list_head_; 1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = head; 1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch present_flags_.Add(value->gvn_flags()); // Keep it. 1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValue* HValueMap::Lookup(HValue* value) const { 1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t hash = static_cast<uint32_t>(value->Hashcode()); 1218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t pos = Bound(hash); 1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (array_[pos].value != NULL) { 1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (array_[pos].value->Equals(value)) return array_[pos].value; 1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next = array_[pos].next; 1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (next != kNil) { 1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lists_[next].value->Equals(value)) return lists_[next].value; 1224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next = lists_[next].next; 1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return NULL; 1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Resize(int new_size) { 1232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(new_size > count_); 1233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Hashing the values into the new array has no more collisions than in the 1234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // old hash map, so we can use the existing lists_ array, if we are careful. 1235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Make sure we have at least one free element. 1237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (free_list_head_ == kNil) { 1238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ResizeLists(lists_size_ << 1); 1239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* new_array = 124244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZONE->NewArray<HValueMapListElement>(new_size); 1243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memset(new_array, 0, sizeof(HValueMapListElement) * new_size); 1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* old_array = array_; 1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int old_size = array_size_; 1247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int old_count = count_; 1249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_ = 0; 1250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do not modify present_flags_. It is currently correct. 1251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_size_ = new_size; 1252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_ = new_array; 1253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (old_array != NULL) { 1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Iterate over all the elements in lists, rehashing them. 1256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < old_size; ++i) { 1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (old_array[i].value != NULL) { 1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int current = old_array[i].next; 1259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != kNil) { 1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Insert(lists_[current].value); 1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next = lists_[current].next; 1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[current].next = free_list_head_; 1263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = current; 1264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = next; 1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Rehash the directly stored value. 1267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Insert(old_array[i].value); 1268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch USE(old_count); 1272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(count_ == old_count); 1273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::ResizeLists(int new_size) { 1277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(new_size > lists_size_); 1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* new_lists = 128044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZONE->NewArray<HValueMapListElement>(new_size); 1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memset(new_lists, 0, sizeof(HValueMapListElement) * new_size); 1282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* old_lists = lists_; 1284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int old_size = lists_size_; 1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_size_ = new_size; 1287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_ = new_lists; 1288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (old_lists != NULL) { 1290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(lists_, old_lists, old_size * sizeof(HValueMapListElement)); 1291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = old_size; i < lists_size_; ++i) { 1293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[i].next = free_list_head_; 1294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = i; 1295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Insert(HValue* value) { 1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(value != NULL); 1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Resizing when half of the hashtable is filled up. 1302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (count_ >= array_size_ >> 1) Resize(array_size_ << 1); 1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(count_ < array_size_); 1304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_++; 1305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t pos = Bound(static_cast<uint32_t>(value->Hashcode())); 1306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (array_[pos].value == NULL) { 1307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[pos].value = value; 1308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[pos].next = kNil; 1309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (free_list_head_ == kNil) { 1311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ResizeLists(lists_size_ << 1); 1312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int new_element_pos = free_list_head_; 1314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(new_element_pos != kNil); 1315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = lists_[free_list_head_].next; 1316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[new_element_pos].value = value; 1317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[new_element_pos].next = array_[pos].next; 1318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL); 1319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[pos].next = new_element_pos; 1320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HStackCheckEliminator BASE_EMBEDDED { 1325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 1326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } 1327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Process(); 1329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 1332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::Process() { 1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For each loop block walk the dominator tree from the backwards branch to 1337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the loop header. If a call instruction is encountered the backwards branch 1338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // is dominated by a call and the stack check in the backwards branch can be 1339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // removed. 1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < graph_->blocks()->length(); i++) { 1341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge(); 1344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dominator = back_edge; 13453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch while (true) { 1346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = dominator->first(); 13473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch while (instr != NULL) { 1348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->IsCall()) { 13493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch block->loop_information()->stack_check()->Eliminate(); 13503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 1351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 1353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 13553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Done when the loop header is processed. 13563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (dominator == block) break; 1357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 13583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Move up the dominator tree. 13593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch dominator = dominator->dominator(); 13603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Simple sparse set with O(1) add, contains, and clear. 1367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochclass SparseSet { 1368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch public: 1369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SparseSet(Zone* zone, int capacity) 1370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : capacity_(capacity), 1371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch length_(0), 1372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dense_(zone->NewArray<int>(capacity)), 13733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch sparse_(zone->NewArray<int>(capacity)) { 13743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#ifndef NVALGRIND 13753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Initialize the sparse array to make valgrind happy. 13763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch memset(sparse_, 0, sizeof(sparse_[0]) * capacity); 13773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#endif 13783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool Contains(int n) const { 1381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(0 <= n && n < capacity_); 1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int d = sparse_[n]; 1383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return 0 <= d && d < length_ && dense_[d] == n; 1384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool Add(int n) { 1387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (Contains(n)) return false; 1388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dense_[length_] = n; 1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch sparse_[n] = length_; 1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ++length_; 1391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 1392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch void Clear() { length_ = 0; } 1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int capacity_; 1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int length_; 1399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int* dense_; 1400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int* sparse_; 1401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DISALLOW_COPY_AND_ASSIGN(SparseSet); 1403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch}; 1404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HGlobalValueNumberer BASE_EMBEDDED { 1407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 1408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info) 1409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : graph_(graph), 1410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch info_(info), 14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch removed_side_effects_(false), 1412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block_side_effects_(graph->blocks()->length()), 1413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch loop_side_effects_(graph->blocks()->length()), 1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch visited_on_paths_(graph->zone(), graph->blocks()->length()) { 141544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(info->isolate()->heap()->allow_allocation(false)); 14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch block_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length()); 14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch loop_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length()); 1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ~HGlobalValueNumberer() { 142044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!info_->isolate()->heap()->allow_allocation(true)); 1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Returns true if values with side effects are removed. 14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool Analyze(); 1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( 14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* dominator, 14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* dominated); 1430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AnalyzeBlock(HBasicBlock* block, HValueMap* map); 1431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void ComputeBlockSideEffects(); 1432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void LoopInvariantCodeMotion(); 1433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void ProcessLoopBlock(HBasicBlock* block, 1434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* before_loop, 14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet loop_kills, 14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet* accumulated_first_time_depends, 14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet* accumulated_first_time_changes); 1438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bool AllowCodeMotion(); 1439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); 1440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HGraph* graph() { return graph_; } 1442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CompilationInfo* info() { return info_; } 14438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Zone* zone() { return graph_->zone(); } 1444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 1446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CompilationInfo* info_; 14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool removed_side_effects_; 1448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A map of block IDs to their side effects. 14503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<GVNFlagSet> block_side_effects_; 1451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A map of loop header block IDs to their loop's side effects. 14533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<GVNFlagSet> loop_side_effects_; 1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Used when collecting side effects on paths from dominator to 1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // dominated. 1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SparseSet visited_on_paths_; 1458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGlobalValueNumberer::Analyze() { 14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch removed_side_effects_ = false; 1463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ComputeBlockSideEffects(); 1464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_loop_invariant_code_motion) { 1465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LoopInvariantCodeMotion(); 1466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 14678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValueMap* map = new(zone()) HValueMap(); 14683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AnalyzeBlock(graph_->entry_block(), map); 14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return removed_side_effects_; 1470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ComputeBlockSideEffects() { 14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The Analyze phase of GVN can be called multiple times. Clear loop side 14753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // effects before computing them to erase the contents from previous Analyze 14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // passes. 14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < loop_side_effects_.length(); ++i) { 14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch loop_side_effects_[i].RemoveAll(); 14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute side effects for the block. 1482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int id = block->block_id(); 14853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet side_effects; 1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 14873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch side_effects.Add(instr->ChangesFlags()); 14883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->IsSoftDeoptimize()) { 14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch block_side_effects_[id].RemoveAll(); 14903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch side_effects.RemoveAll(); 14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 14923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 1494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 14953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch block_side_effects_[id].Add(side_effects); 1496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Loop headers are part of their loop. 1498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch loop_side_effects_[id].Add(side_effects); 1500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Propagate loop side effects upwards. 1503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->HasParentLoopHeader()) { 1504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int header_id = block->parent_loop_header()->block_id(); 15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch loop_side_effects_[header_id].Add(block->IsLoopHeader() 15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? loop_side_effects_[id] 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : side_effects); 1508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::LoopInvariantCodeMotion() { 1514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet side_effects = loop_side_effects_[block->block_id()]; 1518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", 1519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->block_id(), 15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch side_effects.ToIntegral()); 1521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet accumulated_first_time_depends; 15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet accumulated_first_time_changes; 1524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* last = block->loop_information()->GetLastBackEdge(); 1525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = block->block_id(); j <= last->block_id(); ++j) { 15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects, 15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &accumulated_first_time_depends, 15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &accumulated_first_time_changes); 1529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGlobalValueNumberer::ProcessLoopBlock( 15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* block, 15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* loop_header, 15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet loop_kills, 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet* first_time_depends, 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet* first_time_changes) { 1541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* pre_header = loop_header->predecessors()->at(0); 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); 1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", 1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->block_id(), 15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depends_flags.ToIntegral()); 1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* next = instr->next(); 15493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool hoisted = false; 15503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->CheckFlag(HValue::kUseGVN)) { 15513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TraceGVN("Checking instruction %d (%s) instruction GVN flags 0x%X, " 15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch "loop kills 0x%X\n", 1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->id(), 15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->Mnemonic(), 15553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->gvn_flags().ToIntegral(), 15563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depends_flags.ToIntegral()); 15573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); 15583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->IsTransitionElementsKind()) { 15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // It's possible to hoist transitions out of a loop as long as the 15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // hoisting wouldn't move the transition past a DependsOn of one of it's 15613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // changes or any instructions that might change an objects map or 15623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // elements contents. 15633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet changes = instr->ChangesFlags(); 15643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet hoist_depends_blockers = 15653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue::ConvertChangesToDependsFlags(changes); 15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // In addition to not hoisting transitions above other instructions that 15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // change dependencies that the transition changes, it must not be 15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // hoisted above map changes and stores to an elements backing store 15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // that the transition might change. 15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet hoist_change_blockers = changes; 15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch hoist_change_blockers.Add(kChangesMaps); 15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr); 15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (trans->original_map()->has_fast_double_elements()) { 15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch hoist_change_blockers.Add(kChangesDoubleArrayElements); 15755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (trans->transitioned_map()->has_fast_double_elements()) { 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch hoist_change_blockers.Add(kChangesArrayElements); 15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TraceGVN("Checking dependencies on HTransitionElementsKind %d (%s) " 15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch "hoist depends blockers 0x%X, hoist change blockers 0x%X, " 15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch "accumulated depends 0x%X, accumulated changes 0x%X\n", 15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->id(), 15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->Mnemonic(), 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch hoist_depends_blockers.ToIntegral(), 15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch hoist_change_blockers.ToIntegral(), 15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch first_time_depends->ToIntegral(), 15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch first_time_changes->ToIntegral()); 15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // It's possible to hoist transition from the current loop loop only if 15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // they dominate all of the successor blocks in the same loop and there 15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // are not any instructions that have Changes/DependsOn that intervene 15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // between it and the beginning of the loop header. 15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool in_nested_loop = block != loop_header && 15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ((block->parent_loop_header() != loop_header) || 15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch block->IsLoopHeader()); 15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch can_hoist = !in_nested_loop && 15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch block->IsLoopSuccessorDominator() && 15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !first_time_depends->ContainsAnyOf(hoist_depends_blockers) && 15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !first_time_changes->ContainsAnyOf(hoist_change_blockers); 1599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (can_hoist) { 16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool inputs_loop_invariant = true; 16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < instr->OperandCount(); ++i) { 16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { 16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inputs_loop_invariant = false; 16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { 16103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TraceGVN("Hoisting loop invariant instruction %d\n", instr->id()); 16113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Move the instruction out of the loop. 16123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->Unlink(); 16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->InsertBefore(pre_header->end()); 16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasSideEffects()) removed_side_effects_ = true; 16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch hoisted = true; 16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 16193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!hoisted) { 16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If an instruction is not hoisted, we have to account for its side 16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // effects when hoisting later HTransitionElementsKind instructions. 16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch first_time_depends->Add(instr->DependsOnFlags()); 16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch first_time_changes->Add(instr->ChangesFlags()); 16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = next; 1626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 16291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool HGlobalValueNumberer::AllowCodeMotion() { 1631e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; 1632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 1633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGlobalValueNumberer::ShouldMove(HInstruction* instr, 1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header) { 16373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If we've disabled code motion or we're in a block that unconditionally 16383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // deoptimizes, don't move any instructions. 16393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return AllowCodeMotion() && !instr->block()->IsDeoptimizing(); 1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochGVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( 1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* dominator, HBasicBlock* dominated) { 16453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet side_effects; 1646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < dominated->predecessors()->length(); ++i) { 1647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* block = dominated->predecessors()->at(i); 1648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (dominator->block_id() < block->block_id() && 1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block->block_id() < dominated->block_id() && 1650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch visited_on_paths_.Add(block->block_id())) { 16513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch side_effects.Add(block_side_effects_[block->block_id()]); 1652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (block->IsLoopHeader()) { 16533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch side_effects.Add(loop_side_effects_[block->block_id()]); 1654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 16553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock( 16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch dominator, block)); 1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return side_effects; 1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { 1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceGVN("Analyzing block B%d%s\n", 1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block->block_id(), 1666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block->IsLoopHeader() ? " (loop header)" : ""); 1667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If this is a loop header kill everything killed by the loop. 1669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->Kill(loop_side_effects_[block->block_id()]); 1671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Go through all instructions of the current block. 1674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* next = instr->next(); 16773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GVNFlagSet flags = instr->ChangesFlags(); 16783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!flags.IsEmpty()) { 1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Clear all instructions in the map that are affected by side effects. 1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->Kill(flags); 1681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Instruction %d kills\n", instr->id()); 16823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->CheckFlag(HValue::kUseGVN)) { 16843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!instr->HasObservableSideEffects()); 1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* other = map->Lookup(instr); 1686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (other != NULL) { 1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(instr->Equals(other) && other->Equals(instr)); 1688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Replacing value %d (%s) with value %d (%s)\n", 1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->id(), 1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->Mnemonic(), 1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->id(), 1692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->Mnemonic()); 16933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasSideEffects()) removed_side_effects_ = true; 1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->DeleteAndReplaceWith(other); 1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->Add(instr); 1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = next; 1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Recursively continue analysis for all immediately dominated blocks. 1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = block->dominated_blocks()->length(); 1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; ++i) { 1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dominated = block->dominated_blocks()->at(i); 1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // No need to copy the map for the last child in the dominator tree. 17078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); 1708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Kill everything killed on any path between this block and the 1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // dominated block. 1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We don't have to traverse these paths if the value map is 1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // already empty. 1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the range of block ids (block_id, dominated_id) is empty 1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // there are no such paths. 1715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!successor_map->IsEmpty() && 1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch block->block_id() + 1 < dominated->block_id()) { 1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch visited_on_paths_.Clear(); 1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch successor_map->Kill(CollectSideEffectsOnPathsToDominatedBlock(block, 1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dominated)); 1720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AnalyzeBlock(dominated, successor_map); 1722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HInferRepresentation BASE_EMBEDDED { 1727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit HInferRepresentation(HGraph* graph) 17293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : graph_(graph), 17303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch worklist_(8), 17313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch in_worklist_(graph->GetMaximumValueID(), graph->zone()) { } 1732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(); 1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation TryChange(HValue* current); 1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AddToWorklist(HValue* current); 1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferBasedOnInputs(HValue* current); 1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AddDependantsToWorklist(HValue* current); 1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferBasedOnUses(HValue* current); 1741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 17428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Zone* zone() { return graph_->zone(); } 17438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 1745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> worklist_; 1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector in_worklist_; 1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddToWorklist(HValue* current) { 1751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->representation().IsSpecialization()) return; 1752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; 1753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (in_worklist_.Contains(current->id())) return; 1754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist_.Add(current); 1755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist_.Add(current->id()); 1756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method tries to specialize the representation type of the value 1760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as a parameter. The value is asked to infer its representation type 1761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// based on its inputs. If the inferred type is more specialized, then this 1762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// becomes the new representation type of the node. 1763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnInputs(HValue* current) { 1764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation r = current->representation(); 1765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (r.IsSpecialization()) return; 1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); 1767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation inferred = current->InferredRepresentation(); 1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (inferred.IsSpecialization()) { 17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_representation) { 17703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("Changing #%d representation %s -> %s based on inputs\n", 17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current->id(), 17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r.Mnemonic(), 17733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inferred.Mnemonic()); 17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->ChangeRepresentation(inferred); 1776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddDependantsToWorklist(current); 1777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HInferRepresentation::AddDependantsToWorklist(HValue* value) { 1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { 1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddToWorklist(it.value()); 1784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < value->OperandCount(); ++i) { 1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddToWorklist(value->OperandAt(i)); 1787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method calculates whether specializing the representation of the value 1792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as the parameter has a benefit in terms of less necessary type 1793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// conversions. If there is a benefit, then the representation of the value is 1794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// specialized. 1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HInferRepresentation::InferBasedOnUses(HValue* value) { 1796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation r = value->representation(); 1797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (r.IsSpecialization() || value->HasNoUses()) return; 1798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(value->CheckFlag(HValue::kFlexibleRepresentation)); 1799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation new_rep = TryChange(value); 1800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!new_rep.IsNone()) { 1801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!value->representation().Equals(new_rep)) { 18023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_representation) { 18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("Changing #%d representation %s -> %s based on uses\n", 18043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value->id(), 18053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r.Mnemonic(), 18063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new_rep.Mnemonic()); 18073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value->ChangeRepresentation(new_rep); 1809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddDependantsToWorklist(value); 1810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochRepresentation HInferRepresentation::TryChange(HValue* value) { 1816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Array of use counts for each representation. 1817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int use_count[Representation::kNumRepresentations] = { 0 }; 1818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { 1820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* use = it.value(); 1821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation rep = use->RequiredInputRepresentation(it.index()); 1822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (rep.IsNone()) continue; 1823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (use->IsPhi()) HPhi::cast(use)->AddIndirectUsesTo(&use_count[0]); 18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch use_count[rep.kind()] += use->LoopWeight(); 1825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int tagged_count = use_count[Representation::kTagged]; 1827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int double_count = use_count[Representation::kDouble]; 1828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int int32_count = use_count[Representation::kInteger32]; 1829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int non_tagged_count = double_count + int32_count; 1830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If a non-loop phi has tagged uses, don't convert it to untagged. 1832589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (value->IsPhi() && !value->block()->IsLoopHeader() && tagged_count > 0) { 1833589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Representation::None(); 1834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1836589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Prefer unboxing over boxing, the latter is more expensive. 18373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (tagged_count > non_tagged_count) return Representation::None(); 1838589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1839589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Prefer Integer32 over Double, if possible. 1840589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (int32_count > 0 && value->IsConvertibleToInteger()) { 1841589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Representation::Integer32(); 1842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1843589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1844589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (double_count > 0) return Representation::Double(); 1845589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::None(); 1847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::Analyze() { 18513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Infer representations", graph_); 1852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // (1) Initialize bit vectors and count real uses. Each phi gets a 1854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // bit-vector of length <number of phis>. 1855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HPhi*>* phi_list = graph_->phi_list(); 1856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int phi_count = phi_list->length(); 1857257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ZoneList<BitVector*> connected_phis(phi_count); 1858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < phi_count; ++i) { 1859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi_list->at(i)->InitRealUses(i); 18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BitVector* connected_set = new(zone()) BitVector(phi_count, graph_->zone()); 1861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch connected_set->Add(i); 1862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch connected_phis.Add(connected_set); 1863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // (2) Do a fixed point iteration to find the set of connected phis. A 1866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // phi is connected to another phi if its value is used either directly or 1867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // indirectly through a transitive closure of the def-use relation. 1868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool change = true; 1869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (change) { 1870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch change = false; 1871589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // We normally have far more "forward edges" than "backward edges", 1872589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // so we terminate faster when we walk backwards. 1873589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch for (int i = phi_count - 1; i >= 0; --i) { 1874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list->at(i); 1875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { 1876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* use = it.value(); 1877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (use->IsPhi()) { 1878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int id = HPhi::cast(use)->phi_id(); 18793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (connected_phis[i]->UnionIsChanged(*connected_phis[id])) 18803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch change = true; 1881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1886589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // (3) Use the phi reachability information from step 2 to 1887589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // (a) sum up the non-phi use counts of all connected phis. 1888589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // (b) push information about values which can't be converted to integer 1889589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // without deoptimization through the phi use-def chains, avoiding 1890589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // unnecessary deoptimizations later. 1891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < phi_count; ++i) { 1892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list->at(i); 1893589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool cti = phi->AllOperandsConvertibleToInteger(); 1894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (BitVector::Iterator it(connected_phis.at(i)); 1895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !it.Done(); 1896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch it.Advance()) { 1897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = it.Current(); 1898589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HPhi* it_use = phi_list->at(it.Current()); 1899589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (index != i) phi->AddNonPhiUsesFrom(it_use); // Don't count twice! 1900589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (!cti) it_use->set_is_convertible_to_integer(false); 1901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1904589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Initialize work list 1905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < graph_->blocks()->length(); ++i) { 1906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HPhi*>* phis = block->phis(); 1908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < phis->length(); ++j) { 1909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToWorklist(phis->at(j)); 1910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = block->first(); 1913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 1914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToWorklist(current); 1915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 1916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1919589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Do a fixed point iteration, trying to improve representations 1920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!worklist_.is_empty()) { 1921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* current = worklist_.RemoveLast(); 1922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist_.Remove(current->id()); 1923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferBasedOnInputs(current); 1924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferBasedOnUses(current); 1925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes() { 19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Inferring types", this); 1931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InitializeInferredTypes(0, this->blocks_.length() - 1); 1932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) { 1936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = from_inclusive; i <= to_inclusive; ++i) { 1937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = blocks_[i]; 1938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HPhi*>* phis = block->phis(); 1940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < phis->length(); j++) { 1941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis->at(j)->UpdateInferredType(); 1942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = block->first(); 1945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 1946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->UpdateInferredType(); 1947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 1948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* last_back_edge = 1952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->loop_information()->GetLastBackEdge(); 1953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InitializeInferredTypes(i + 1, last_back_edge->block_id()); 1954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Skip all blocks already processed by the recursive call. 1955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch i = last_back_edge->block_id(); 1956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Update phis of the loop header now after the whole loop body is 1957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // guaranteed to be processed. 1958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> worklist(block->phis()->length()); 1959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < block->phis()->length(); ++j) { 1960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist.Add(block->phis()->at(j)); 1961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferTypes(&worklist); 1963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) { 1969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* current = value; 1970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 1971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (visited->Contains(current->id())) return; 1972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For phis, we must propagate the check to all of its inputs. 1974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->IsPhi()) { 1975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visited->Add(current->id()); 1976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = HPhi::cast(current); 1977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phi->OperandCount(); ++i) { 1978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(phi->OperandAt(i), visited); 1979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For multiplication and division, we must propagate to the left and 1984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the right side. 1985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->IsMul()) { 1986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HMul* mul = HMul::cast(current); 1987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch mul->EnsureAndPropagateNotMinusZero(visited); 1988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(mul->left(), visited); 1989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(mul->right(), visited); 1990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (current->IsDiv()) { 1991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HDiv* div = HDiv::cast(current); 1992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch div->EnsureAndPropagateNotMinusZero(visited); 1993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(div->left(), visited); 1994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(div->right(), visited); 1995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->EnsureAndPropagateNotMinusZero(visited); 1998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChangeForUse(HValue* value, 2003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* use_value, 2004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int use_index, 2005e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Representation to) { 2006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Insert the representation change right before its use. For phi-uses we 2007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // insert at the end of the corresponding predecessor. 20081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HInstruction* next = NULL; 2009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (use_value->IsPhi()) { 2010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch next = use_value->block()->predecessors()->at(use_index)->end(); 20111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 2012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch next = HInstruction::cast(use_value); 2013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For constants we try to make the representation change at compile 2016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // time. When a representation change is not possible without loss of 2017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // information we treat constants like normal instructions and insert the 2018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // change instructions for them. 2019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* new_value = NULL; 2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32); 2021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool deoptimize_on_undefined = 2022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch use_value->CheckFlag(HValue::kDeoptimizeOnUndefined); 2023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value->IsConstant()) { 2024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* constant = HConstant::cast(value); 2025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Try to create a new copy of the constant with the new representation. 2026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_value = is_truncating 2027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? constant->CopyToTruncatedInt32() 2028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : constant->CopyToRepresentation(to); 2029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (new_value == NULL) { 20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new_value = new(zone()) HChange(value, to, 20337d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch is_truncating, deoptimize_on_undefined); 2034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_value->InsertBefore(next); 2037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch use_value->SetOperandAt(use_index, new_value); 2038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraph::InsertRepresentationChangesForValue(HValue* value) { 2042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation r = value->representation(); 2043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (r.IsNone()) return; 2044257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (value->HasNoUses()) return; 2045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (HUseIterator it(value->uses()); !it.Done(); it.Advance()) { 2047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* use_value = it.value(); 2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int use_index = it.index(); 2049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation req = use_value->RequiredInputRepresentation(use_index); 2050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (req.IsNone() || req.Equals(r)) continue; 2051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InsertRepresentationChangeForUse(value, use_value, use_index, req); 2052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (value->HasNoUses()) { 2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(value->IsConstant()); 2055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value->DeleteAndReplaceWith(NULL); 2056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The only purpose of a HForceRepresentation is to represent the value 2059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // after the (possible) HChange instruction. We make it disappear. 2060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (value->IsForceRepresentation()) { 2061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value->DeleteAndReplaceWith(HForceRepresentation::cast(value)->value()); 2062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChanges() { 20673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Representation changes", this); 2068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute truncation flag for phis: Initially assume that all 2070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // int32-phis allow truncation and iteratively remove the ones that 2071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // are used in an operation that does not allow a truncating 2072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // conversion. 2073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(fschneider): Replace this with a worklist-based iteration. 2074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phi_list()->length(); i++) { 2075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list()->at(i); 2076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (phi->representation().IsInteger32()) { 2077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->SetFlag(HValue::kTruncatingToInt32); 2078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool change = true; 2081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (change) { 2082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch change = false; 2083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phi_list()->length(); i++) { 2084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list()->at(i); 2085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; 20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!phi->CheckUsesForFlag(HValue::kTruncatingToInt32)) { 20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch phi->ClearFlag(HValue::kTruncatingToInt32); 20883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch change = true; 2089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 2094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Process phi instructions first. 2095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const ZoneList<HPhi*>* phis = blocks_[i]->phis(); 2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int j = 0; j < phis->length(); j++) { 2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InsertRepresentationChangesForValue(phis->at(j)); 2098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Process normal instructions. 2101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = blocks_[i]->first(); 2102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 2103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch InsertRepresentationChangesForValue(current); 2104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 2105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 21107d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdochvoid HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) { 21117d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return; 21127d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch phi->SetFlag(HValue::kDeoptimizeOnUndefined); 21137d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch for (int i = 0; i < phi->OperandCount(); ++i) { 21147d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch HValue* input = phi->OperandAt(i); 21157d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch if (input->IsPhi()) { 21167d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi::cast(input)); 21177d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 21187d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 21197d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch} 21207d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch 21217d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch 21227d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdochvoid HGraph::MarkDeoptimizeOnUndefined() { 21233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_MarkDeoptimizeOnUndefined", this); 21247d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // Compute DeoptimizeOnUndefined flag for phis. 21257d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // Any phi that can reach a use with DeoptimizeOnUndefined set must 21263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have DeoptimizeOnUndefined set. Currently only HCompareIDAndBranch, with 21277d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // double input representation, has this flag set. 21287d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // The flag is used by HChange tagged->double, which must deoptimize 21297d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // if one of its uses has this flag set. 21307d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch for (int i = 0; i < phi_list()->length(); i++) { 21317d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch HPhi* phi = phi_list()->at(i); 21327d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch if (phi->representation().IsDouble()) { 2133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) { 2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (it.value()->CheckFlag(HValue::kDeoptimizeOnUndefined)) { 21357d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch RecursivelyMarkPhiDeoptimizeOnUndefined(phi); 21367d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch break; 21377d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 21387d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 21397d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 21407d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 21417d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch} 21427d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch 21437d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch 21441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid HGraph::ComputeMinusZeroChecks() { 21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BitVector visited(GetMaximumValueID(), zone()); 21461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < blocks_.length(); ++i) { 21471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (HInstruction* current = blocks_[i]->first(); 21481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block current != NULL; 21491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block current = current->next()) { 21501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (current->IsChange()) { 21511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HChange* change = HChange::cast(current); 21521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Propagate flags for negative zero checks upwards from conversions 21531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // int32-to-tagged and int32-to-double. 21541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Representation from = change->value()->representation(); 21551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(from.Equals(change->from())); 21561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (from.IsInteger32()) { 21571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(change->to().IsTagged() || change->to().IsDouble()); 21581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(visited.IsEmpty()); 21591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PropagateMinusZeroChecks(change->value(), &visited); 21601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block visited.Clear(); 21611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 21621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 21631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 21641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 21651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 21661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 21671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Implementation of utility class to encapsulate the translation state for 2169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// a (possibly inlined) function. 2170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochFunctionState::FunctionState(HGraphBuilder* owner, 2171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CompilationInfo* info, 21723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TypeFeedbackOracle* oracle, 21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ReturnHandlingFlag return_handling) 2174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : owner_(owner), 2175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch compilation_info_(info), 2176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch oracle_(oracle), 2177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch call_context_(NULL), 21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return_handling_(return_handling), 2179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch function_return_(NULL), 2180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch test_context_(NULL), 2181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch outer_(owner->function_state()) { 2182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (outer_ != NULL) { 2183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // State for an inline function. 2184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (owner->ast_context()->IsTest()) { 2185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 2186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 2187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if_true->MarkAsInlineReturnTarget(); 2188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if_false->MarkAsInlineReturnTarget(); 21893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Expression* cond = TestContext::cast(owner->ast_context())->condition(); 2190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The AstContext constructor pushed on the context stack. This newed 2191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // instance is the reason that AstContext can't be BASE_EMBEDDED. 21923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch test_context_ = new TestContext(owner, cond, if_true, if_false); 2193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 2194e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch function_return_ = owner->graph()->CreateBasicBlock(); 2195e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch function_return()->MarkAsInlineReturnTarget(); 2196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Set this after possibly allocating a new TestContext above. 2198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch call_context_ = owner->ast_context(); 2199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2200e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Push on the state stack. 2202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch owner->set_function_state(this); 2203e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochFunctionState::~FunctionState() { 2207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch delete test_context_; 2208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch owner_->set_function_state(outer_); 2209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Implementation of utility classes to represent an expression's context in 2213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the AST. 2214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) 22158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : owner_(owner), 22168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch kind_(kind), 22178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch outer_(owner->ast_context()), 22188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for_typeof_(false) { 2219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner->set_ast_context(this); // Push. 2220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 22213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(owner->environment()->frame_type() == JS_FUNCTION); 22229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block original_length_ = owner->environment()->length(); 2223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 2224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::~AstContext() { 2228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner_->set_ast_context(outer_); // Pop. 2229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochEffectContext::~EffectContext() { 2233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(owner()->HasStackOverflow() || 2234e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch owner()->current_block() == NULL || 22353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (owner()->environment()->length() == original_length_ && 22363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch owner()->environment()->frame_type() == JS_FUNCTION)); 2237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochValueContext::~ValueContext() { 2241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(owner()->HasStackOverflow() || 2242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch owner()->current_block() == NULL || 22433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (owner()->environment()->length() == original_length_ + 1 && 22443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch owner()->environment()->frame_type() == JS_FUNCTION)); 2245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnValue(HValue* value) { 2249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The value is simply ignored. 2250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnValue(HValue* value) { 2254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The value is tracked in the bailout environment, and communicated 2255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // through the environment as the result of the expression. 2256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) { 2257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch owner()->Bailout("bad value context for arguments value"); 2258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->Push(value); 2260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnValue(HValue* value) { 2264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildBranch(value); 2265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) { 22693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(!instr->IsControlInstruction()); 2270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->AddInstruction(instr); 22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id); 2272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid EffectContext::ReturnControl(HControlInstruction* instr, int ast_id) { 22763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!instr->HasObservableSideEffects()); 22773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); 22783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); 22793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->SetSuccessorAt(0, empty_true); 22803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->SetSuccessorAt(1, empty_false); 22813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->current_block()->Finish(instr); 22823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id); 22833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->set_current_block(join); 22843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 22853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 22863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { 22883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(!instr->IsControlInstruction()); 2289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { 22903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return owner()->Bailout("bad value context for arguments object value"); 2291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->AddInstruction(instr); 2293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->Push(instr); 22943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id); 2295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid ValueContext::ReturnControl(HControlInstruction* instr, int ast_id) { 22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!instr->HasObservableSideEffects()); 23003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) { 23013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return owner()->Bailout("bad value context for arguments object value"); 23023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 23033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock(); 23043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock(); 23053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->SetSuccessorAt(0, materialize_true); 23063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->SetSuccessorAt(1, materialize_false); 23073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->current_block()->Finish(instr); 23083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->set_current_block(materialize_true); 23093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->Push(owner()->graph()->GetConstantTrue()); 23103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->set_current_block(materialize_false); 23113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->Push(owner()->graph()->GetConstantFalse()); 23123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* join = 23133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->CreateJoin(materialize_true, materialize_false, ast_id); 23143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->set_current_block(join); 23153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 23163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 23173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { 23193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(!instr->IsControlInstruction()); 2320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder* builder = owner(); 2321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->AddInstruction(instr); 2322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We expect a simulate after every expression with side effects, though 2323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // this one isn't actually needed (and wouldn't work if it were targeted). 23243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) { 2325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->Push(instr); 2326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->AddSimulate(ast_id); 2327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->Pop(); 2328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildBranch(instr); 2330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 23333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid TestContext::ReturnControl(HControlInstruction* instr, int ast_id) { 23343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!instr->HasObservableSideEffects()); 23353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock(); 23363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock(); 23373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->SetSuccessorAt(0, empty_true); 23383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->SetSuccessorAt(1, empty_false); 23393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->current_block()->Finish(instr); 23403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch empty_true->Goto(if_true(), owner()->function_state()->drop_extra()); 23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch empty_false->Goto(if_false(), owner()->function_state()->drop_extra()); 23423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch owner()->set_current_block(NULL); 23433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 23443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 23453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::BuildBranch(HValue* value) { 2347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We expect the graph to be in edge-split form: there is no edge that 2348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // connects a branch node to a join node. We conservatively ensure that 2349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // property by always adding an empty block on the outgoing edges of this 2350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // branch. 2351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder* builder = owner(); 23523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (value != NULL && value->CheckFlag(HValue::kIsArguments)) { 2353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch builder->Bailout("arguments object value in a test context"); 2354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 235769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch unsigned test_id = condition()->test_id(); 235869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id)); 235969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); 2360e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch builder->current_block()->Finish(test); 2361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 23623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch empty_true->Goto(if_true(), owner()->function_state()->drop_extra()); 23633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch empty_false->Goto(if_false(), owner()->function_state()->drop_extra()); 2364e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch builder->set_current_block(NULL); 2365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// HGraphBuilder infrastructure for bailing out and checking bailouts. 2369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define CHECK_BAILOUT(call) \ 2370053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block do { \ 2371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call; \ 2372053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block if (HasStackOverflow()) return; \ 2373053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } while (false) 2374053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 2375053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block 2376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#define CHECK_ALIVE(call) \ 2377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { \ 2378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call; \ 2379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return; \ 2380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (false) 2381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::Bailout(const char* reason) { 2384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_bailout) { 2385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SmartArrayPointer<char> name( 2386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch info()->shared_info()->DebugName()->ToCString()); 2387e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason); 2388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetStackOverflow(); 2390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForEffect(Expression* expr) { 2394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EffectContext for_effect(this); 2395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr); 2396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitForValue(Expression* expr, ArgumentsAllowedFlag flag) { 2400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ValueContext for_value(this, flag); 2401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr); 2402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 24058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid HGraphBuilder::VisitForTypeOf(Expression* expr) { 2406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED); 24078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for_value.set_for_typeof(true); 24088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Visit(expr); 24098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 24108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 24118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 24128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForControl(Expression* expr, 2414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* true_block, 2415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* false_block) { 24163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch TestContext for_test(this, expr, true_block, false_block); 2417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr); 2418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 24213fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHValue* HGraphBuilder::VisitArgument(Expression* expr) { 24223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitForValue(expr); 24233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return NULL; 24243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* value = Pop(); 24253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Push(AddInstruction(new(zone()) HPushArgument(value))); 24263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return value; 2427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { 2431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < arguments->length(); i++) { 2432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgument(arguments->at(i))); 2433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { 2438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < exprs->length(); ++i) { 2439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(exprs->at(i))); 2440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2443e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHGraph* HGraphBuilder::CreateGraph() { 24458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch graph_ = new(zone()) HGraph(info()); 244644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info()); 2447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 24493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Block building"); 245044f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block_ = graph()->entry_block(); 2451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Scope* scope = info()->scope(); 2453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (scope->HasIllegalRedeclaration()) { 2454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Bailout("function with illegal redeclaration"); 2455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return NULL; 2456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 24573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (scope->calls_eval()) { 24583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Bailout("function calls eval"); 24593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return NULL; 24603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SetUpScope(scope); 2462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Add an edge to the body entry. This is warty: the graph's start 2464e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // environment will be used by the Lithium translation as the initial 2465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // environment on graph entry, but it has now been mutated by the 2466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Hydrogen translation of the instructions in the start block. This 2467e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // environment uses values which have not been defined yet. These 2468e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Hydrogen instructions will then be replayed by the Lithium 2469e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // translation, so they cannot have an environment effect. The edge to 2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the body's entry block (along with some special logic for the start 2471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // block in HInstruction::InsertAfter) seals the start block from 2472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // getting unwanted instructions inserted. 2473e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // 2474e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(kmillikin): Fix this. Stop mutating the initial environment. 2475e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Make the Hydrogen instructions in the initial block into Hydrogen 2476e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // values (but not instructions), present in the initial environment and 2477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // not replayed by the Lithium translation. 2478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HEnvironment* initial_env = environment()->CopyWithoutHistory(); 2479e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_entry = CreateBasicBlock(initial_env); 2480e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(body_entry); 24818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch body_entry->SetJoinId(AstNode::kFunctionEntryId); 2482e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(body_entry); 2483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2484589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Handle implicit declaration of the function name in named function 2485589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // expressions before other declarations. 2486589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (scope->is_function_scope() && scope->function() != NULL) { 24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HandleDeclaration(scope->function(), CONST, NULL, NULL); 2488589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2489589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VisitDeclarations(scope->declarations()); 2490589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddSimulate(AstNode::kDeclarationsId); 2491589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2492589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = environment()->LookupContext(); 2493589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddInstruction( 2494589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch new(zone()) HStackCheck(context, HStackCheck::kFunctionEntry)); 2495589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitStatements(info()->function()->body()); 2497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return NULL; 2498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2499e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (current_block() != NULL) { 25008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); 2501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->FinishExit(instr); 2502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 2503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2506e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch graph()->OrderBlocks(); 2507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch graph()->AssignDominators(); 25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG 25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do a full verify after building the graph and computing dominators. 25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch graph()->Verify(true); 25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 251469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch graph()->PropagateDeoptimizingMark(); 25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!graph()->CheckConstPhiUses()) { 25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Bailout("Unsupported phi use of const variable"); 25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return NULL; 25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2519592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch graph()->EliminateRedundantPhis(); 25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!graph()->CheckArgumentsPhiUses()) { 25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Bailout("Unsupported phi use of arguments"); 2522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return NULL; 2523589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2524592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); 25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch graph()->CollectPhis(); 25263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 25273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (graph()->has_osr_loop_entry()) { 25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const ZoneList<HPhi*>* phis = graph()->osr_loop_entry()->phis(); 25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int j = 0; j < phis->length(); j++) { 25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhi* phi = phis->at(j); 25313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch graph()->osr_values()->at(phi->merged_index())->set_incoming_value(phi); 25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 25335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 25345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HInferRepresentation rep(graph()); 2536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch rep.Analyze(); 2537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 25387d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch graph()->MarkDeoptimizeOnUndefined(); 2539e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch graph()->InsertRepresentationChanges(); 2540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 254169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch graph()->InitializeInferredTypes(); 254269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch graph()->Canonicalize(); 2543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Perform common subexpression elimination and loop-invariant code motion. 2545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_use_gvn) { 25463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Global value numbering", graph()); 2547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HGlobalValueNumberer gvn(graph(), info()); 25483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool removed_side_effects = gvn.Analyze(); 25493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Trigger a second analysis pass to further eliminate duplicate values that 25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // could only be discovered by removing side-effect-generating instructions 25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // during the first pass. 25523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_smi_only_arrays && removed_side_effects) { 25533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch removed_side_effects = gvn.Analyze(); 25543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!removed_side_effects); 25553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 255869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (FLAG_use_range) { 255969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HRangeAnalysis rangeAnalysis(graph()); 256069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch rangeAnalysis.Analyze(); 256169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 256269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch graph()->ComputeMinusZeroChecks(); 256369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 256469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Eliminate redundant stack checks on backwards branches. 256569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HStackCheckEliminator sce(graph()); 256669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch sce.Process(); 256769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 25687d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // Replace the results of check instructions with the original value, if the 25697d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // result is used. This is safe now, since we don't do code motion after this 25707d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // point. It enables better register allocation since the value produced by 25717d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // check instructions is really a copy of the original value. 25727d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch graph()->ReplaceCheckedValues(); 25737d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch 2574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return graph(); 2575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 25787d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdochvoid HGraph::ReplaceCheckedValues() { 25793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HPhase phase("H_Replace checked values", this); 25807d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch for (int i = 0; i < blocks()->length(); ++i) { 25817d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch HInstruction* instr = blocks()->at(i)->first(); 25827d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch while (instr != NULL) { 25837d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch if (instr->IsBoundsCheck()) { 25847d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch // Replace all uses of the checked value with the original input. 2585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(instr->UseCount() > 0); 2586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->ReplaceAllUsesWith(HBoundsCheck::cast(instr)->index()); 25877d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 25887d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch instr = instr->next(); 25897d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 25907d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch } 25917d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch} 25927d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch 25937d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch 2594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 2595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 2596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->AddInstruction(instr); 2597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 2598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 26013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::AddSimulate(int ast_id) { 2602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 26033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->AddSimulate(ast_id); 2604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddPhi(HPhi* instr) { 2608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 2609e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->AddPhi(instr); 2610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::PushAndAdd(HInstruction* instr) { 2614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(instr); 2615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 2616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 26193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochtemplate <class Instruction> 26203ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHInstruction* HGraphBuilder::PreProcessCall(Instruction* call) { 26211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int count = call->argument_count(); 26221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ZoneList<HValue*> arguments(count); 26231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < count; ++i) { 26241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block arguments.Add(Pop()); 2625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 26271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block while (!arguments.is_empty()) { 26288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); 2629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2630e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return call; 2631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 26343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::SetUpScope(Scope* scope) { 26358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HConstant* undefined_constant = new(zone()) HConstant( 263644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->factory()->undefined_value(), Representation::Tagged()); 2637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(undefined_constant); 2638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->set_undefined_constant(undefined_constant); 2639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HArgumentsObject* object = new(zone()) HArgumentsObject; 26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(object); 26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch graph()->SetArgumentsObject(object); 26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Set the initial values of parameters including "this". "This" has 2645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // parameter index 0. 2646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(scope->num_parameters() + 1, environment()->parameter_count()); 2647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < environment()->parameter_count(); ++i) { 26498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); 2650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->Bind(i, parameter); 2651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // First special is HContext. 2654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HInstruction* context = AddInstruction(new(zone()) HContext); 2655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch environment()->BindContext(context); 2656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Initialize specials and locals to undefined. 2658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = environment()->parameter_count() + 1; 2659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch i < environment()->length(); 2660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ++i) { 2661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->Bind(i, undefined_constant); 2662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Handle the arguments and arguments shadow variables specially (they do 2665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // not have declarations). 2666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (scope->arguments() != NULL) { 26673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!scope->arguments()->IsStackAllocated()) { 2668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("context-allocated arguments"); 2669e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 26713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->Bind(scope->arguments(), 26723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch graph()->GetArgumentsObject()); 26733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 2674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { 2678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < statements->length(); i++) { 2679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(Visit(statements->at(i))); 2680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 2685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* b = graph()->CreateBasicBlock(); 2686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch b->SetInitialEnvironment(env); 2687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return b; 2688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2691e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { 2692e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* header = graph()->CreateBasicBlock(); 2693e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); 2694e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch header->SetInitialEnvironment(entry_env); 2695e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch header->AttachLoopInformation(); 2696e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return header; 2697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBlock(Block* stmt) { 2701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 2702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 2703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 270469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch if (stmt->block_scope() != NULL) { 270569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return Bailout("ScopedBlock"); 270669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 2707e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueInfo break_info(stmt); 2708e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { BreakAndContinueScope push(&break_info, this); 2709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitStatements(stmt->statements())); 2710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2711e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* break_block = break_info.break_block(); 2712e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (break_block != NULL) { 2713e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (current_block() != NULL) current_block()->Goto(break_block); 2714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break_block->SetJoinId(stmt->ExitId()); 2715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(break_block); 2716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { 2721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 2722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 2723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForEffect(stmt->expression()); 2725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { 2729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 2730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 2731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitIfStatement(IfStatement* stmt) { 2736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 2737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 2738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt->condition()->ToBooleanIsTrue()) { 2740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(stmt->ThenId()); 2741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(stmt->then_statement()); 2742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (stmt->condition()->ToBooleanIsFalse()) { 2743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(stmt->ElseId()); 2744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(stmt->else_statement()); 2745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* cond_true = graph()->CreateBasicBlock(); 2747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* cond_false = graph()->CreateBasicBlock(); 2748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); 2749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cond_true->HasPredecessor()) { 2751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_true->SetJoinId(stmt->ThenId()); 2752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(cond_true); 2753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(Visit(stmt->then_statement())); 2754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_true = current_block(); 2755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_true = NULL; 2757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cond_false->HasPredecessor()) { 2760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_false->SetJoinId(stmt->ElseId()); 2761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(cond_false); 2762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(Visit(stmt->else_statement())); 2763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_false = current_block(); 2764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 2765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_false = NULL; 2766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 27683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId()); 2769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(join); 2770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( 2775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakableStatement* stmt, 27763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BreakType type, 27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int* drop_extra) { 27783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *drop_extra = 0; 2779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueScope* current = this; 2780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (current != NULL && current->info()->target() != stmt) { 27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *drop_extra += current->info()->drop_extra(); 2782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current = current->next(); 2783e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2784e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current != NULL); // Always found (unless stack is malformed). 27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (type == BREAK) { 27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *drop_extra += current->info()->drop_extra(); 27883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 27893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* block = NULL; 2791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch switch (type) { 2792e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case BREAK: 2793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch block = current->info()->break_block(); 2794e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (block == NULL) { 2795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch block = current->owner()->graph()->CreateBasicBlock(); 2796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current->info()->set_break_block(block); 2797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case CONTINUE: 2801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch block = current->info()->continue_block(); 2802e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (block == NULL) { 2803e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch block = current->owner()->graph()->CreateBasicBlock(); 2804e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current->info()->set_continue_block(block); 2805e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2806e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2808e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2809e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return block; 2810e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2811e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2812e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { 2814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 2815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 2816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 28173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int drop_extra = 0; 28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* continue_block = break_scope()->Get(stmt->target(), 28193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CONTINUE, 28203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &drop_extra); 28213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Drop(drop_extra); 2822e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(continue_block); 2823e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 2824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { 2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 2829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 2830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 28313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int drop_extra = 0; 28323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* break_block = break_scope()->Get(stmt->target(), 28333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BREAK, 28343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &drop_extra); 28353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Drop(drop_extra); 2836e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(break_block); 2837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 2838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 2842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 2843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 2844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AstContext* context = call_context(); 2846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (context == NULL) { 2847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Not an inlined return, so an actual one. 2848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(stmt->expression())); 2849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* result = environment()->Pop(); 28508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch current_block()->FinishExit(new(zone()) HReturn(result)); 28513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (function_state()->is_construct()) { 28523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Return from an inlined construct call. In a test context the return 28533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // value will always evaluate to true, in a value context the return value 28543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // needs to be a JSObject. 28553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (context->IsTest()) { 28563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TestContext* test = TestContext::cast(context); 28573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForEffect(stmt->expression())); 28583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Goto(test->if_true(), function_state()->drop_extra()); 28593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (context->IsEffect()) { 28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForEffect(stmt->expression())); 28613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Goto(function_return(), function_state()->drop_extra()); 28623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 28633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(context->IsValue()); 28643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForValue(stmt->expression())); 28653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* return_value = Pop(); 28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* receiver = environment()->Lookup(0); 28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HHasInstanceTypeAndBranch* typecheck = 28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HHasInstanceTypeAndBranch(return_value, 28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FIRST_SPEC_OBJECT_TYPE, 28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LAST_SPEC_OBJECT_TYPE); 28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); 28723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); 28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch typecheck->SetSuccessorAt(0, if_spec_object); 28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch typecheck->SetSuccessorAt(1, not_spec_object); 28753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Finish(typecheck); 28763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if_spec_object->AddLeaveInlined(return_value, 28773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_return(), 28783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_state()->drop_extra()); 28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch not_spec_object->AddLeaveInlined(receiver, 28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_return(), 28813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_state()->drop_extra()); 28823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return from an inlined function, visit the subexpression in the 2885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // expression context of the call. 2886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (context->IsTest()) { 2887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestContext* test = TestContext::cast(context); 2888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForControl(stmt->expression(), 2889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch test->if_true(), 2890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch test->if_false()); 289144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (context->IsEffect()) { 2892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForEffect(stmt->expression())); 28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Goto(function_return(), function_state()->drop_extra()); 2894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 289544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(context->IsValue()); 2896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(stmt->expression())); 28973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* return_value = Pop(); 28983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->AddLeaveInlined(return_value, 28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_return(), 29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_state()->drop_extra()); 2901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 29033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(NULL); 2904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 290769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdochvoid HGraphBuilder::VisitWithStatement(WithStatement* stmt) { 2908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 2910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 291169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return Bailout("WithStatement"); 2912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 2917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 2918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 291944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We only optimize switch statements with smi-literal smi comparisons, 292044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // with a bounded number of clauses. 292144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int kCaseClauseLimit = 128; 292244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZoneList<CaseClause*>* clauses = stmt->cases(); 292344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int clause_count = clauses->length(); 292444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (clause_count > kCaseClauseLimit) { 2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("SwitchStatement: too many clauses"); 292644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 292744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 29283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* context = environment()->LookupContext(); 29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(stmt->tag())); 2931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(stmt->EntryId()); 293244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* tag_value = Pop(); 293344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* first_test_block = current_block(); 2934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 29353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SwitchType switch_type = UNKNOWN_SWITCH; 29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 1. Extract clause type 293844f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < clause_count; ++i) { 2939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CaseClause* clause = clauses->at(i); 2940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (clause->is_default()) continue; 29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (switch_type == UNKNOWN_SWITCH) { 29433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (clause->label()->IsSmiLiteral()) { 29443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch_type = SMI_SWITCH; 29453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (clause->label()->IsStringLiteral()) { 29463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch_type = STRING_SWITCH; 29473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 29483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("SwitchStatement: non-literal switch label"); 29493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if ((switch_type == STRING_SWITCH && 29513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !clause->label()->IsStringLiteral()) || 29523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (switch_type == SMI_SWITCH && 29533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !clause->label()->IsSmiLiteral())) { 29543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("SwitchStatemnt: mixed label types are not supported"); 2955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 29563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2957592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 29583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HUnaryControlInstruction* string_check = NULL; 29593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* not_string_block = NULL; 29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Test switch's tag value if all clauses are string literals 29623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (switch_type == STRING_SWITCH) { 29633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch string_check = new(zone()) HIsStringAndBranch(tag_value); 29643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch first_test_block = graph()->CreateBasicBlock(); 29653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch not_string_block = graph()->CreateBasicBlock(); 29663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch string_check->SetSuccessorAt(0, first_test_block); 29683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch string_check->SetSuccessorAt(1, not_string_block); 29693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Finish(string_check); 29703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(first_test_block); 29723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 2. Build all the tests, with dangling true branches 29753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int default_id = AstNode::kNoNumber; 29763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < clause_count; ++i) { 29773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CaseClause* clause = clauses->at(i); 29783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (clause->is_default()) { 29793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch default_id = clause->EntryId(); 29803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch continue; 29813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 29823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (switch_type == SMI_SWITCH) { 29833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch clause->RecordTypeFeedback(oracle()); 2984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Generate a compare and branch. 2987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(clause->label())); 298844f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* label_value = Pop(); 29893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 299085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 29913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* body_block = graph()->CreateBasicBlock(); 29923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HControlInstruction* compare; 29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (switch_type == SMI_SWITCH) { 29963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!clause->IsSmiCompare()) { 29973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Finish with deoptimize and add uses of enviroment values to 29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // account for invisible uses. 29993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); 30003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(NULL); 30013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 30023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 30033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HCompareIDAndBranch* compare_ = 30053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCompareIDAndBranch(tag_value, 30063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch label_value, 30073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::EQ_STRICT); 30083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare_->SetInputRepresentation(Representation::Integer32()); 30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare = compare_; 30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 30113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare = new(zone()) HStringCompareAndBranch(context, tag_value, 30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch label_value, 30133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::EQ_STRICT); 30143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 30153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch compare->SetSuccessorAt(0, body_block); 30173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch compare->SetSuccessorAt(1, next_test_block); 30183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->Finish(compare); 30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 302044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(next_test_block); 302144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 302244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 302344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Save the current block to use for the default or to join with the 302444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // exit. This block is NULL if we deoptimized. 302544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* last_block = current_block(); 302644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 30273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (not_string_block != NULL) { 30283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int join_id = (default_id != AstNode::kNoNumber) 30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? default_id 30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : stmt->ExitId(); 30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch last_block = CreateJoin(last_block, not_string_block, join_id); 30323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 30333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 3. Loop over the clauses and the linked list of tests in lockstep, 303544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // translating the clause bodies. 303644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* curr_test_block = first_test_block; 303744f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* fall_through_block = NULL; 30383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 303944f0eee88ff00398ff7f715fab053374d808c90dSteve Block BreakAndContinueInfo break_info(stmt); 304044f0eee88ff00398ff7f715fab053374d808c90dSteve Block { BreakAndContinueScope push(&break_info, this); 304144f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < clause_count; ++i) { 304244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CaseClause* clause = clauses->at(i); 304344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 304444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Identify the block where normal (non-fall-through) control flow 304544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // goes to. 304644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* normal_block = NULL; 3047053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block if (clause->is_default()) { 3048053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block if (last_block != NULL) { 3049053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block normal_block = last_block; 3050053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block last_block = NULL; // Cleared to indicate we've handled it. 3051053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block } 305244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (!curr_test_block->end()->IsDeoptimize()) { 305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block normal_block = curr_test_block->end()->FirstSuccessor(); 305444f0eee88ff00398ff7f715fab053374d808c90dSteve Block curr_test_block = curr_test_block->end()->SecondSuccessor(); 305544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 3056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 305744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Identify a block to emit the body into. 305844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (normal_block == NULL) { 305944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (fall_through_block == NULL) { 306044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (a) Unreachable. 306144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (clause->is_default()) { 306244f0eee88ff00398ff7f715fab053374d808c90dSteve Block continue; // Might still be reachable clause bodies. 306344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 306444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 306544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 306644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 306744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (b) Reachable only as fall through. 306844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(fall_through_block); 3069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 307044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (fall_through_block == NULL) { 307144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (c) Reachable only normally. 307244f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(normal_block); 3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 307444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (d) Reachable both ways. 307544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* join = CreateJoin(fall_through_block, 307644f0eee88ff00398ff7f715fab053374d808c90dSteve Block normal_block, 307744f0eee88ff00398ff7f715fab053374d808c90dSteve Block clause->EntryId()); 307844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(join); 3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitStatements(clause->statements())); 308244f0eee88ff00398ff7f715fab053374d808c90dSteve Block fall_through_block = current_block(); 3083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 308644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Create an up-to-3-way join. Use the break block if it exists since 308744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // it's already a join block. 308844f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* break_block = break_info.break_block(); 308944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (break_block == NULL) { 309044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(CreateJoin(fall_through_block, 309144f0eee88ff00398ff7f715fab053374d808c90dSteve Block last_block, 309244f0eee88ff00398ff7f715fab053374d808c90dSteve Block stmt->ExitId())); 3093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 309444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (fall_through_block != NULL) fall_through_block->Goto(break_block); 309544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (last_block != NULL) last_block->Goto(break_block); 309644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break_block->SetJoinId(stmt->ExitId()); 309744f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(break_block); 3098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 310144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { 3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return statement->OsrEntryId() == info()->osr_ast_id(); 3104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { 31083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!HasOsrEntryAt(statement)) return false; 3109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); 3111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* osr_entry = graph()->CreateBasicBlock(); 3112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* true_value = graph()->GetConstantTrue(); 31133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBranch* test = new(zone()) HBranch(true_value, non_osr_entry, osr_entry); 3114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Finish(test); 3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); 3117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch non_osr_entry->Goto(loop_predecessor); 3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(osr_entry); 3120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int osr_entry_id = statement->OsrEntryId(); 31213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int first_expression_index = environment()->first_expression_index(); 31223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int length = environment()->length(); 31233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<HUnknownOSRValue*>* osr_values = 31243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) ZoneList<HUnknownOSRValue*>(length); 31253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < first_expression_index; ++i) { 3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue; 3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(osr_value); 3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch environment()->Bind(i, osr_value); 31303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch osr_values->Add(osr_value); 31315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 31325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (first_expression_index != length) { 31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->Drop(length - first_expression_index); 31353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = first_expression_index; i < length; ++i) { 31363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue; 31373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(osr_value); 31383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->Push(osr_value); 31393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch osr_values->Add(osr_value); 31403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 31413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 31423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch graph()->set_osr_values(osr_values); 31443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3145e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddSimulate(osr_entry_id); 31468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); 3147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HContext* context = new(zone()) HContext; 3148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(context); 3149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch environment()->BindContext(context); 3150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(loop_predecessor); 3151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_predecessor->SetJoinId(statement->EntryId()); 3152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_predecessor); 31533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 3154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitLoopBody(IterationStatement* stmt, 31583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* loop_entry, 31593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BreakAndContinueInfo* break_info) { 31603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BreakAndContinueScope push(break_info, this); 31613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddSimulate(stmt->StackCheckId()); 31623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 31633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStackCheck* stack_check = 31643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HStackCheck(context, HStackCheck::kBackwardsBranch); 31653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(stack_check); 31663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(loop_entry->IsLoopHeader()); 31673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch loop_entry->loop_information()->set_stack_check(stack_check); 31683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_BAILOUT(Visit(stmt->body())); 31693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 31703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 31713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 3173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 31773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool osr_entry = PreProcessOsrEntry(stmt); 3178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 31793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->Goto(loop_entry); 3180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_entry); 31813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (osr_entry) graph()->set_osr_loop_entry(loop_entry); 3182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueInfo break_info(stmt); 31843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); 3185e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_exit = 3186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch JoinContinue(stmt, current_block(), break_info.continue_block()); 3187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_successor = NULL; 3188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { 3189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(body_exit); 3190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The block for a true condition, the actual predecessor block of the 3191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // back edge. 3192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch body_exit = graph()->CreateBasicBlock(); 3193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor = graph()->CreateBasicBlock(); 3194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor)); 3195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (body_exit->HasPredecessor()) { 3196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch body_exit->SetJoinId(stmt->BackEdgeId()); 3197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch body_exit = NULL; 3199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (loop_successor->HasPredecessor()) { 3201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch loop_successor->SetJoinId(stmt->ExitId()); 3202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch loop_successor = NULL; 3204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_exit = CreateLoop(stmt, 3207e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_entry, 3208e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch body_exit, 3209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor, 3210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break_info.break_block()); 3211e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_exit); 3212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { 3216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3219e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 32203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool osr_entry = PreProcessOsrEntry(stmt); 3221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 32223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->Goto(loop_entry); 3223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_entry); 32243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (osr_entry) graph()->set_osr_loop_entry(loop_entry); 32253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If the condition is constant true, do not generate a branch. 3228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_successor = NULL; 3229e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!stmt->cond()->ToBooleanIsTrue()) { 3230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_entry = graph()->CreateBasicBlock(); 3231e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor = graph()->CreateBasicBlock(); 3232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); 3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (body_entry->HasPredecessor()) { 3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch body_entry->SetJoinId(stmt->BodyId()); 3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(body_entry); 3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (loop_successor->HasPredecessor()) { 3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch loop_successor->SetJoinId(stmt->ExitId()); 3239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch loop_successor = NULL; 3241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3244e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueInfo break_info(stmt); 3245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (current_block() != NULL) { 32463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); 3247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_exit = 3249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch JoinContinue(stmt, current_block(), break_info.continue_block()); 3250e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_exit = CreateLoop(stmt, 3251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_entry, 3252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch body_exit, 3253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor, 3254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break_info.break_block()); 3255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_exit); 3256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForStatement(ForStatement* stmt) { 3260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (stmt->init() != NULL) { 3264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(Visit(stmt->init())); 3265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 32673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool osr_entry = PreProcessOsrEntry(stmt); 3268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 32693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->Goto(loop_entry); 3270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_entry); 32713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (osr_entry) graph()->set_osr_loop_entry(loop_entry); 3272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_successor = NULL; 3274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt->cond() != NULL) { 3275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_entry = graph()->CreateBasicBlock(); 3276e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor = graph()->CreateBasicBlock(); 3277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); 3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (body_entry->HasPredecessor()) { 3279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch body_entry->SetJoinId(stmt->BodyId()); 3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(body_entry); 3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (loop_successor->HasPredecessor()) { 3283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch loop_successor->SetJoinId(stmt->ExitId()); 3284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch loop_successor = NULL; 3286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueInfo break_info(stmt); 3290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (current_block() != NULL) { 32913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); 3292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3293e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_exit = 3294e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch JoinContinue(stmt, current_block(), break_info.continue_block()); 3295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3296e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (stmt->next() != NULL && body_exit != NULL) { 3297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(body_exit); 3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(Visit(stmt->next())); 3299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch body_exit = current_block(); 3300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_exit = CreateLoop(stmt, 3303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_entry, 3304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch body_exit, 3305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor, 3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break_info.break_block()); 3307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_exit); 3308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { 3312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 33153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!FLAG_optimize_for_in) { 33173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("ForInStatement optimization is disabled"); 33183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 33193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!oracle()->IsForInFastCase(stmt)) { 33213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("ForInStatement is not fast case"); 33223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 33233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!stmt->each()->IsVariableProxy() || 33253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { 33263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("ForInStatement with non-local each variable"); 33273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 33283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Variable* each_var = stmt->each()->AsVariableProxy()->var(); 33303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForValue(stmt->enumerable())); 33323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* enumerable = Top(); // Leave enumerable at the top. 33333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* map = AddInstruction(new(zone()) HForInPrepareMap( 33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->LookupContext(), enumerable)); 33363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddSimulate(stmt->PrepareId()); 33373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* array = AddInstruction( 33393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HForInCacheArray( 33403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch enumerable, 33413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map, 33423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DescriptorArray::kEnumCacheBridgeCacheIndex)); 33433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* array_length = AddInstruction( 33453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HFixedArrayBaseLength(array)); 33463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* start_index = AddInstruction(new(zone()) HConstant( 33483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object>(Smi::FromInt(0)), Representation::Integer32())); 33493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(map); 33513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(array); 33523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(array_length); 33533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(start_index); 33543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* index_cache = AddInstruction( 33563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HForInCacheArray( 33573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch enumerable, 33583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map, 33593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DescriptorArray::kEnumCacheBridgeIndicesCacheIndex)); 33603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HForInCacheArray::cast(array)->set_index_cache( 33613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HForInCacheArray::cast(index_cache)); 33623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool osr_entry = PreProcessOsrEntry(stmt); 33643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 33653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Goto(loop_entry); 33663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(loop_entry); 33673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (osr_entry) graph()->set_osr_loop_entry(loop_entry); 33683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* index = environment()->ExpressionStackAt(0); 33703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* limit = environment()->ExpressionStackAt(1); 33713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that we still have more keys. 33733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HCompareIDAndBranch* compare_index = 33743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCompareIDAndBranch(index, limit, Token::LT); 33753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare_index->SetInputRepresentation(Representation::Integer32()); 33763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* loop_body = graph()->CreateBasicBlock(); 33783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* loop_successor = graph()->CreateBasicBlock(); 33793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare_index->SetSuccessorAt(0, loop_body); 33813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare_index->SetSuccessorAt(1, loop_successor); 33823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Finish(compare_index); 33833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(loop_successor); 33853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Drop(5); 33863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(loop_body); 33883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* key = AddInstruction( 33903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HLoadKeyedFastElement( 33913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->ExpressionStackAt(2), // Enum cache. 33923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->ExpressionStackAt(0), // Iteration index. 33933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HLoadKeyedFastElement::OMIT_HOLE_CHECK)); 33943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 33953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if the expected map still matches that of the enumerable. 33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If not just deoptimize. 33973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckMapValue( 33983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->ExpressionStackAt(4), 33993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->ExpressionStackAt(3))); 34003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Bind(each_var, key); 34023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BreakAndContinueInfo break_info(stmt, 5); 34043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); 34053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* body_exit = 34073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JoinContinue(stmt, current_block(), break_info.continue_block()); 34083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (body_exit != NULL) { 34103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(body_exit); 34113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* current_index = Pop(); 34133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* new_index = new(zone()) HAdd(environment()->LookupContext(), 34143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_index, 34153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch graph()->GetConstant1()); 34163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new_index->AssumeRepresentation(Representation::Integer32()); 34173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PushAndAdd(new_index); 34183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch body_exit = current_block(); 34193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 34203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* loop_exit = CreateLoop(stmt, 34223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch loop_entry, 34233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch body_exit, 34243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch loop_successor, 34253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break_info.break_block()); 34263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 34273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(loop_exit); 3428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 3432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("TryCatchStatement"); 3436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("TryFinallyStatement"); 3444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("DebuggerStatement"); 34528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 34538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 34548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 34558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic Handle<SharedFunctionInfo> SearchSharedFunctionInfo( 34568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Code* unoptimized_code, FunctionLiteral* expr) { 34578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int start_position = expr->start_position(); 34588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocIterator it(unoptimized_code); 34598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (;!it.done(); it.next()) { 34608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo* rinfo = it.rinfo(); 34618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; 34628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Object* obj = rinfo->target_object(); 34638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (obj->IsSharedFunctionInfo()) { 34648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); 34658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (shared->start_position() == start_position) { 34668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Handle<SharedFunctionInfo>(shared); 34678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 34688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 34698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 34708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 34718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Handle<SharedFunctionInfo>(); 3472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<SharedFunctionInfo> shared_info = 34808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SearchSharedFunctionInfo(info()->shared_info()->code(), 34818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr); 34828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (shared_info.is_null()) { 34838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); 34848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We also have a stack overflow if the recursive compilation did. 3486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasStackOverflow()) return; 34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 3488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HFunctionLiteral* instr = 34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HFunctionLiteral(context, shared_info, expr->pretenure()); 34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 3491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSharedFunctionInfoLiteral( 3495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SharedFunctionInfoLiteral* expr) { 3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("SharedFunctionInfoLiteral"); 3500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitConditional(Conditional* expr) { 3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3507e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* cond_true = graph()->CreateBasicBlock(); 3508e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* cond_false = graph()->CreateBasicBlock(); 3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); 3510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 351144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Visit the true and false subexpressions in the same AST context as the 351244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // whole expression. 3513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cond_true->HasPredecessor()) { 3514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_true->SetJoinId(expr->ThenId()); 3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(cond_true); 3516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(Visit(expr->then_expression())); 3517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_true = current_block(); 3518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_true = NULL; 3520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (cond_false->HasPredecessor()) { 3523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_false->SetJoinId(expr->ElseId()); 3524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(cond_false); 3525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(Visit(expr->else_expression())); 3526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_false = current_block(); 3527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch cond_false = NULL; 3529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 353144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!ast_context()->IsTest()) { 3532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); 353344f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(join); 3534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (join != NULL && !ast_context()->IsEffect()) { 35353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(Pop()); 3536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 353744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 3538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 35418b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochHGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( 35428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Variable* var, LookupResult* lookup, bool is_store) { 35438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (var->is_this() || !info()->has_global_object()) { 35448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return kUseGeneric; 3545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<GlobalObject> global(info()->global_object()); 3547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch global->Lookup(*var->name(), lookup); 35483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!lookup->IsFound() || 35498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch lookup->type() != NORMAL || 35508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch (is_store && lookup->IsReadOnly()) || 35518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch lookup->holder() != *global) { 35528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return kUseGeneric; 35531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 35558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return kUseCell; 35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 35571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35591e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockHValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { 35601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(var->IsContextSlot()); 3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 3562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int length = info()->scope()->ContextChainLength(var->scope()); 35631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block while (length-- > 0) { 3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HInstruction* context_instruction = new(zone()) HOuterContext(context); 3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(context_instruction); 3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context = context_instruction; 35671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return context; 3569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 3573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3576589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* variable = expr->var(); 3577589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (variable->location()) { 3578589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: { 35793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (variable->mode() == LET || variable->mode() == CONST_HARMONY) { 35803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("reference to global harmony declared variable"); 35813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 35823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Handle known global constants like 'undefined' specially to avoid a 35833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // load from a global cell for them. 35843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> constant_value = 35853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->GlobalConstantFor(variable->name()); 35863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!constant_value.is_null()) { 35873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HConstant* instr = 35883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HConstant(constant_value, Representation::Tagged()); 35893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 35903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 35913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 3593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch GlobalPropertyAccess type = 3594589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch LookupGlobalProperty(variable, &lookup, false); 3595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3596589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (type == kUseCell && 3597589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch info()->global_object()->IsAccessCheckNeeded()) { 3598589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch type = kUseGeneric; 3599589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 3600589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 3601589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (type == kUseCell) { 3602589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Handle<GlobalObject> global(info()->global_object()); 3603589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 36043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HLoadGlobalCell* instr = 36053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HLoadGlobalCell(cell, lookup.GetPropertyDetails()); 3606589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 3607589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 3608589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = environment()->LookupContext(); 3609589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 3610589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddInstruction(global_object); 3611589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HLoadGlobalGeneric* instr = 3612589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch new(zone()) HLoadGlobalGeneric(context, 3613589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch global_object, 3614589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch variable->name(), 3615589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ast_context()->is_for_typeof()); 3616589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch instr->set_position(expr->position()); 3617589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 3618589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 36198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 36208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3621589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 3622589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: { 3623589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* value = environment()->Lookup(variable); 36243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (value == graph()->GetConstantHole()) { 36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(variable->mode() == CONST || 36263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch variable->mode() == CONST_HARMONY || 36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch variable->mode() == LET); 36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("reference to uninitialized variable"); 3629589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 3630589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ast_context()->ReturnValue(value); 3631589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 3632589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 3633589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: { 3634589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = BuildContextChainWalk(variable); 36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, variable); 36363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 3637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3638589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 3639589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: 3640589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Bailout("reference to a variable which requires dynamic lookup"); 3641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitLiteral(Literal* expr) { 3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 36498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HConstant* instr = 36508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HConstant(expr->handle(), Representation::Tagged()); 36513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 3652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 36593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 36603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HRegExpLiteral* instr = new(zone()) HRegExpLiteral(context, 36623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch expr->pattern(), 36638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->flags(), 36648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->literal_index()); 36653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 3666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 36693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Determines whether the given array or object literal boilerplate satisfies 36703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// all limits to be considered for fast deep-copying and computes the total 36713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// size of all objects that are part of the graph. 36723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsFastLiteral(Handle<JSObject> boilerplate, 36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int max_depth, 36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int* max_properties, 36753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int* total_size) { 36763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(max_depth >= 0 && *max_properties >= 0); 36773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (max_depth == 0) return false; 36783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArrayBase> elements(boilerplate->elements()); 36803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements->length() > 0 && 36813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { 36823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (boilerplate->HasFastDoubleElements()) { 36833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *total_size += FixedDoubleArray::SizeFor(elements->length()); 36843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (boilerplate->HasFastElements()) { 36853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int length = elements->length(); 36863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < length; i++) { 36873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if ((*max_properties)-- == 0) return false; 36883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value = JSObject::GetElement(boilerplate, i); 36893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (value->IsJSObject()) { 36903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> value_object = Handle<JSObject>::cast(value); 36913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!IsFastLiteral(value_object, 36923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch max_depth - 1, 36933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch max_properties, 36943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch total_size)) { 36953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 36963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 36973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 36983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 36993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *total_size += FixedArray::SizeFor(length); 37003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 37013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 37023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> properties(boilerplate->properties()); 37063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (properties->length() > 0) { 37073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 37083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 37093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int nof = boilerplate->map()->inobject_properties(); 37103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < nof; i++) { 37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if ((*max_properties)-- == 0) return false; 37123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> value(boilerplate->InObjectPropertyAt(i)); 37133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (value->IsJSObject()) { 37143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> value_object = Handle<JSObject>::cast(value); 37153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!IsFastLiteral(value_object, 37163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch max_depth - 1, 37173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch max_properties, 37183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch total_size)) { 37193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 37203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *total_size += boilerplate->map()->instance_size(); 37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> closure = function_state()->compilation_info()->closure(); 3735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* literal; 37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check whether to use fast or slow deep-copying for boilerplate. 37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int total_size = 0; 37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int max_properties = HFastLiteral::kMaxLiteralProperties; 37413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> boilerplate(closure->literals()->get(expr->literal_index())); 37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (boilerplate->IsJSObject() && 37433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch IsFastLiteral(Handle<JSObject>::cast(boilerplate), 37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HFastLiteral::kMaxLiteralDepth, 37453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &max_properties, 37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &total_size)) { 37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); 37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch literal = new(zone()) HFastLiteral(context, 37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch boilerplate_object, 37503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch total_size, 37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->literal_index(), 37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->depth()); 37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch literal = new(zone()) HObjectLiteral(context, 37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->constant_properties(), 37563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->fast_elements(), 37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->literal_index(), 37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->depth(), 37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->has_function()); 37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The object is expected in the bailout environment during computation 3763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the property values and is the value of the entire expression. 3764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(literal); 3765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->CalculateEmitStore(); 3767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < expr->properties()->length(); i++) { 3769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ObjectLiteral::Property* property = expr->properties()->at(i); 3770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (property->IsCompileTimeValue()) continue; 3771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* key = property->key(); 3773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* value = property->value(); 3774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (property->kind()) { 3776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::MATERIALIZED_LITERAL: 3777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 3778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Fall through. 3779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::COMPUTED: 3780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (key->handle()->IsSymbol()) { 3781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (property->emit_store()) { 37823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch property->RecordTypeFeedback(oracle()); 3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(value)); 3784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* store = BuildStoreNamed(literal, value, property); 37861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(store); 37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (store->HasObservableSideEffects()) AddSimulate(key->id()); 3788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForEffect(value)); 3790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 3792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Fall through. 3794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::PROTOTYPE: 3795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::SETTER: 3796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::GETTER: 3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("Object literal with complex property"); 3798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: UNREACHABLE(); 3799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 380144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 380244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (expr->has_function()) { 380344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return the result of the transformation to fast properties 380444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // instead of the original since this operation changes the map 380544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // of the object. This makes sure that the original object won't 380644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // be used by other optimized code before it is transformed 380744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (e.g. because of code motion). 38088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HToFastProperties* result = new(zone()) HToFastProperties(Pop()); 380944f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(result); 38103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(result); 381144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 38123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(Pop()); 381344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 3814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 3818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<Expression*>* subexprs = expr->values(); 3822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = subexprs->length(); 38233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 38243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* literal; 38253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> literals(environment()->closure()->literals()); 38273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); 38283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (raw_boilerplate->IsUndefined()) { 38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( 38313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate(), literals, expr->constant_elements()); 38323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (raw_boilerplate.is_null()) { 38333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("array boilerplate creation failed"); 38343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 38353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch literals->set(expr->literal_index(), *raw_boilerplate); 38363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (JSObject::cast(*raw_boilerplate)->elements()->map() == 38373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->heap()->fixed_cow_array_map()) { 38383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->counters()->cow_arrays_created_runtime()->Increment(); 38393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 38403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 38413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> boilerplate = Handle<JSObject>::cast(raw_boilerplate); 38433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind boilerplate_elements_kind = 38443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>::cast(boilerplate)->GetElementsKind(); 38453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check whether to use fast or slow deep-copying for boilerplate. 38473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int total_size = 0; 38483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int max_properties = HFastLiteral::kMaxLiteralProperties; 38493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (IsFastLiteral(boilerplate, 38503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HFastLiteral::kMaxLiteralDepth, 38513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &max_properties, 38523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &total_size)) { 38533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch literal = new(zone()) HFastLiteral(context, 38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch boilerplate, 38553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch total_size, 38563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->literal_index(), 38573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->depth()); 38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 38593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch literal = new(zone()) HArrayLiteral(context, 38603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch boilerplate, 38613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch length, 38623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->literal_index(), 38633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->depth()); 38643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3865c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 3866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The array is expected in the bailout environment during computation 3867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the property values and is the value of the entire expression. 3868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(literal); 3869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HLoadElements* elements = NULL; 3871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; i++) { 3873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* subexpr = subexprs->at(i); 3874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the subexpression is a literal or a simple materialized literal it 3875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // is already set in the cloned array. 3876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 3877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(subexpr)); 3879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 3880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); 3881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 38823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements = new(zone()) HLoadElements(literal); 38833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(elements); 3884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 38858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValue* key = AddInstruction( 38868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), 38878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Representation::Integer32())); 38883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 38893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch (boilerplate_elements_kind) { 38903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 38913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Smi-only arrays need a smi check. 38923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckSmi(value)); 38933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fall through. 38943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_ELEMENTS: 38953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HStoreKeyedFastElement( 38963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements, 38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch key, 38983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 38993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch boilerplate_elements_kind)); 39003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 39013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_DOUBLE_ELEMENTS: 39023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements, 39033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch key, 39043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value)); 39053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 39063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch default: 39073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 39083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 39093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 39103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(expr->GetIdForElement(i)); 3912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 39133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(Pop()); 3914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Sets the lookup result and returns true if the store can be inlined. 3918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool ComputeStoredField(Handle<Map> type, 3919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup) { 3921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch type->LookupInDescriptors(NULL, *name, lookup); 39223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!lookup->IsFound()) return false; 3923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup->type() == FIELD) return true; 3924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return (lookup->type() == MAP_TRANSITION) && 3925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (type->unused_property_fields() > 0); 3926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int ComputeStoredFieldIndex(Handle<Map> type, 3930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup) { 3932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(lookup->type() == FIELD || lookup->type() == MAP_TRANSITION); 3933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup->type() == FIELD) { 3934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return lookup->GetLocalFieldIndexFromMap(*type); 3935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Map* transition = lookup->GetTransitionMapFromMap(*type); 3937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return transition->PropertyIndexFor(*name) - type->inobject_properties(); 3938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, 3943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 3945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> type, 3946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup, 3947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool smi_and_map_check) { 3948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (smi_and_map_check) { 39498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); 39503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckMap(object, type, NULL, 39513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS)); 3952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = ComputeStoredFieldIndex(type, name, lookup); 3955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_in_object = index < 0; 3956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = index * kPointerSize; 3957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (index < 0) { 3958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Negative property indices are in-object properties, indexed 3959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // from the end of the fixed part of the object. 3960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch offset += type->instance_size(); 3961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch offset += FixedArray::kHeaderSize; 3963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HStoreNamedField* instr = 39658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); 3966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup->type() == MAP_TRANSITION) { 3967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); 3968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_transition(transition); 3969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(fschneider): Record the new map type of the object in the IR to 3970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // enable elimination of redundant checks after the transition store. 39713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->SetGVNFlag(kChangesMaps); 3972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 3974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, 3978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value) { 3980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 39818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HStoreNamedGeneric( 39828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch context, 39838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch object, 39848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch name, 39858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch value, 39863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_strict_mode_flag()); 39873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 39883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39903ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, 39913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* value, 39923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ObjectLiteral::Property* prop) { 39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Literal* key = prop->key()->AsLiteral(); 39943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name = Handle<String>::cast(key->handle()); 39953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!name.is_null()); 39963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 39973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 39983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> type = prop->GetReceiverType(); 39993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_monomorphic = prop->IsMonomorphic() && 40003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ComputeStoredField(type, name, &lookup); 40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 40023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return is_monomorphic 40033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? BuildStoreNamedField(object, name, value, type, &lookup, 40043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch true) // Needs smi and map check. 40053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : BuildStoreNamedGeneric(object, name, value); 40065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 40075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 40085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 40095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, 40105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* value, 4011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* expr) { 4012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = (expr->AsProperty() != NULL) 4013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? expr->AsProperty() 4014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : expr->AsAssignment()->target()->AsProperty(); 4015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* key = prop->key()->AsLiteral(); 4016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = Handle<String>::cast(key->handle()); 4017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!name.is_null()); 4018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 40193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 402069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SmallMapList* types = expr->GetReceiverTypes(); 4021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_monomorphic = expr->IsMonomorphic() && 4022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ComputeStoredField(types->first(), name, &lookup); 4023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return is_monomorphic 4025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? BuildStoreNamedField(object, name, value, types->first(), &lookup, 4026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true) // Needs smi and map check. 4027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : BuildStoreNamedGeneric(object, name, value); 4028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, 4032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* object, 4033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 403469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SmallMapList* types, 4035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name) { 4036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(ager): We should recognize when the prototype chains for different 4037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // maps are identical. In that case we can avoid repeatedly generating the 4038e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // same prototype map checks. 4039e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int count = 0; 4040e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* join = NULL; 4041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { 4042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = types->at(i); 40433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 4044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (ComputeStoredField(map, name, &lookup)) { 4045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (count == 0) { 40468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); // Only needed once. 4047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch join = graph()->CreateBasicBlock(); 4048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ++count; 4050e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_true = graph()->CreateBasicBlock(); 4051e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_false = graph()->CreateBasicBlock(); 40528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCompareMap* compare = 40538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCompareMap(object, map, if_true, if_false); 4054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Finish(compare); 4055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(if_true); 4057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = 4058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildStoreNamedField(object, name, value, map, &lookup, false); 4059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 4060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Goto will add the HSimulate for the store. 4061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 4062e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!ast_context()->IsEffect()) Push(value); 4063e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(join); 4064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(if_false); 4066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4069e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Finish up. Unconditionally deoptimize if we've handled all the maps we 4070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // know about and do not want to handle ones we've never seen. Otherwise 4071e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // use a generic IC. 4072e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 4073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); 4074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 40751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HInstruction* instr = BuildStoreNamedGeneric(object, name, value); 4076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 4077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 4078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4079e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (join != NULL) { 4080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!ast_context()->IsEffect()) Push(value); 4081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(join); 4082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 4083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The HSimulate for the store should not see the stored value in 4084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // effect contexts (it is not materialized at expr->id() in the 4085e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // unoptimized code). 40863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) { 4087e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (ast_context()->IsEffect()) { 4088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddSimulate(expr->id()); 4089e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 4090e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Push(value); 4091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddSimulate(expr->id()); 4092e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 4093e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4094e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 40953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(value); 40969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 4097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(join != NULL); 4100e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch join->SetJoinId(expr->id()); 4101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(join); 41023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); 4103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 4107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = expr->target()->AsProperty(); 4108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(prop != NULL); 4109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->RecordTypeFeedback(oracle()); 4110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 4111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = NULL; 4113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 4114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->key()->IsPropertyName()) { 4116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named store. 4117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 4118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = Pop(); 4119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* object = Pop(); 4120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* key = prop->key()->AsLiteral(); 4122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = Handle<String>::cast(key->handle()); 4123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!name.is_null()); 4124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 412569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SmallMapList* types = expr->GetReceiverTypes(); 41263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 4127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->IsMonomorphic()) { 4129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = BuildStoreNamed(object, value, expr); 4130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (types != NULL && types->length() > 1) { 4132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandlePolymorphicStoreNamedField(expr, object, value, types, name); 4133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 41361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr = BuildStoreNamedGeneric(object, name, value); 4137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed store. 4141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 4142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 4143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = Pop(); 4144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 4145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* object = Pop(); 41463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool has_side_effects = false; 41473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HandleKeyedElementAccess(object, key, value, expr, expr->AssignmentId(), 41483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch expr->position(), 41493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch true, // is_store 41503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &has_side_effects); 41513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Push(value); 41523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(has_side_effects); // Stores always have side effects. 41533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddSimulate(expr->AssignmentId()); 41543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(Pop()); 4155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(value); 4157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 4158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 41593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); 41603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(Pop()); 4161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Because not every expression has a position and there is not common 4165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// superclass of Assignment and CountOperation, we cannot just pass the 4166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// owning expression instead of position and ast_id separately. 4167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, 4168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 4169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int position, 4170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 41713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 41728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); 41738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (type == kUseCell) { 41748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<GlobalObject> global(info()->global_object()); 41758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 41763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* instr = 41773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); 41788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr->set_position(position); 41798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(instr); 41803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) AddSimulate(ast_id); 41818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 4182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 41838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 41848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(global_object); 41858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStoreGlobalGeneric* instr = 41868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HStoreGlobalGeneric(context, 41878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch global_object, 41888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch var->name(), 41898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch value, 41903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_strict_mode_flag()); 41918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr->set_position(position); 41928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(instr); 41933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(instr->HasObservableSideEffects()); 41943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) AddSimulate(ast_id); 41958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 4196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 4200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* target = expr->target(); 4201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = target->AsVariableProxy(); 4202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = target->AsProperty(); 4203589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(proxy == NULL || prop == NULL); 4204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We have a second position recorded in the FullCodeGenerator to have 4206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // type feedback for the binary operation. 4207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BinaryOperation* operation = expr->binary_operation(); 4208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy != NULL) { 4210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == LET) { 42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("unsupported let compound assignment"); 42133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 42143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(operation)); 4216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4217589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 4218589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: 4219589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HandleGlobalVariableAssignment(var, 4220589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Top(), 4221589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch expr->position(), 4222589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch expr->AssignmentId()); 4223589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 4224589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 4225589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 4226589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 42273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == CONST) { 42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("unsupported const compound assignment"); 42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4230589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Bind(var, Top()); 4231589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 4232589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 4233589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: { 4234589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Bail out if we try to mutate a parameter value in a function 4235589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // using the arguments object. We do not (yet) correctly handle the 4236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // arguments property of the function. 4237589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (info()->scope()->arguments() != NULL) { 4238589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Parameters will be allocated to context slots. We have no 4239589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // direct way to detect that the variable is a parameter so we do 4240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // a linear search of the parameter variables. 4241589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int count = info()->scope()->num_parameters(); 4242589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch for (int i = 0; i < count; ++i) { 4243589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var == info()->scope()->parameter(i)) { 4244589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Bailout( 4245589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch "assignment to parameter, function uses arguments object"); 4246589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 42473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 42483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4249589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 42503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HStoreContextSlot::Mode mode; 42513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch (var->mode()) { 42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case LET: 42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode = HStoreContextSlot::kCheckDeoptimize; 42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case CONST: 42573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnValue(Pop()); 42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case CONST_HARMONY: 42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This case is checked statically so no need to 42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // perform checks here 42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch default: 42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode = HStoreContextSlot::kNoCheck; 42643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4266589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = BuildContextChainWalk(var); 4267589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HStoreContextSlot* instr = 42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HStoreContextSlot(context, var->index(), mode, Top()); 4269589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddInstruction(instr); 42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) { 42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddSimulate(expr->AssignmentId()); 42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4273589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 42743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 42753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4276589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: 4277589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Bailout("compound assignment to lookup slot"); 4278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 42793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(Pop()); 4280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (prop != NULL) { 4282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prop->RecordTypeFeedback(oracle()); 4283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->key()->IsPropertyName()) { 4285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named property. 4286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 4287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Top(); 4288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* load = NULL; 4290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->IsMonomorphic()) { 4291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = prop->GetReceiverTypes()->first(); 4293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamed(obj, prop, map, name); 4294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamedGeneric(obj, prop); 4296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 42983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (load->HasObservableSideEffects()) AddSimulate(expr->CompoundLoadId()); 4299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 4301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 4302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 4303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = BuildBinaryOperation(operation, left, right); 4305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(instr); 43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); 4307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* store = BuildStoreNamed(obj, instr, prop); 4309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 4310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop the simulated receiver and value. Return the value. 4311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(2); 4312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(instr); 43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); 43143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(Pop()); 4315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed property. 4318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 4319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 4320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = environment()->ExpressionStackAt(1); 4321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = environment()->ExpressionStackAt(0); 4322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 43233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool has_side_effects = false; 43243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* load = HandleKeyedElementAccess( 43253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch obj, key, NULL, prop, expr->CompoundLoadId(), RelocInfo::kNoPosition, 43263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch false, // is_store 43273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &has_side_effects); 43283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Push(load); 43293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (has_side_effects) AddSimulate(expr->CompoundLoadId()); 43303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 4333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 4334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 4335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = BuildBinaryOperation(operation, left, right); 4337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(instr); 43383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) AddSimulate(operation->id()); 4339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 43408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->RecordTypeFeedback(oracle()); 43413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HandleKeyedElementAccess(obj, key, instr, expr, expr->AssignmentId(), 43423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RelocInfo::kNoPosition, 43433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch true, // is_store 43443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &has_side_effects); 43453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop the simulated receiver, key, and value. Return the value. 4347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(3); 4348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(instr); 43493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(has_side_effects); // Stores always have side effects. 43503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddSimulate(expr->AssignmentId()); 43513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(Pop()); 4352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("invalid lhs in compound assignment"); 4356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitAssignment(Assignment* expr) { 4361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 4362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 4363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 4364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = expr->target()->AsVariableProxy(); 4365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = expr->target()->AsProperty(); 4366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ASSERT(proxy == NULL || prop == NULL); 4367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->is_compound()) { 4369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleCompoundAssignment(expr); 4370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4373589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (prop != NULL) { 4374589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HandlePropertyAssignment(expr); 4375589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL) { 4376589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 43773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == CONST) { 43793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (expr->op() != Token::INIT_CONST) { 43803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 43813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnValue(Pop()); 43823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 43833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->IsStackAllocated()) { 43853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We insert a use of the old value to detect unsupported uses of const 43863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // variables (e.g. initialization inside a loop). 43873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* old_value = environment()->Lookup(var); 43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new HUseConst(old_value)); 43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 43903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (var->mode() == CONST_HARMONY) { 43913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->op() != Token::INIT_CONST_HARMONY) { 43923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("non-initializer assignment to const"); 439385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 43943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 43953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (proxy->IsArguments()) return Bailout("assignment to arguments"); 4397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Handle the assignment. 4399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 4400589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: 4401589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 4402589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HandleGlobalVariableAssignment(var, 4403589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Top(), 4404589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch expr->position(), 4405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch expr->AssignmentId()); 4406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ast_context()->ReturnValue(Pop()); 4407589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 4408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 4409589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: { 44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Perform an initialization check for let declared variables 44113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // or parameters. 44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == LET && expr->op() == Token::ASSIGN) { 44133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* env_value = environment()->Lookup(var); 44143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (env_value == graph()->GetConstantHole()) { 44153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("assignment to let variable before initialization"); 44163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4418589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // We do not allow the arguments object to occur in a context where it 4419589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // may escape, but assignments to stack-allocated locals are 4420589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // permitted. 4421589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED)); 4422589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* value = Pop(); 4423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Bind(var, value); 4424589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ast_context()->ReturnValue(value); 4425589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 44263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: { 4428589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Bail out if we try to mutate a parameter value in a function using 4429589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // the arguments object. We do not (yet) correctly handle the 4430589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // arguments property of the function. 4431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (info()->scope()->arguments() != NULL) { 4432589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Parameters will rewrite to context slots. We have no direct way 4433589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // to detect that the variable is a parameter. 4434589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int count = info()->scope()->num_parameters(); 4435589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch for (int i = 0; i < count; ++i) { 4436589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var == info()->scope()->parameter(i)) { 4437589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Bailout("assignment to parameter in arguments object"); 4438589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 44393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 44403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 44411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4442589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HStoreContextSlot::Mode mode; 44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->op() == Token::ASSIGN) { 44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch (var->mode()) { 44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case LET: 44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode = HStoreContextSlot::kCheckDeoptimize; 44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case CONST: 44503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnValue(Pop()); 44513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case CONST_HARMONY: 44523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // This case is checked statically so no need to 44533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // perform checks here 44543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 44553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch default: 44563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode = HStoreContextSlot::kNoCheck; 44573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (expr->op() == Token::INIT_VAR || 44593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->op() == Token::INIT_LET || 44603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->op() == Token::INIT_CONST_HARMONY) { 44613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode = HStoreContextSlot::kNoCheck; 44623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 44633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(expr->op() == Token::INIT_CONST); 44643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch mode = HStoreContextSlot::kCheckIgnoreAssignment; 44663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 44673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 4468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = BuildContextChainWalk(var); 44693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HStoreContextSlot* instr = new(zone()) HStoreContextSlot( 44703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context, var->index(), mode, Top()); 4471589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddInstruction(instr); 44723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) { 44733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddSimulate(expr->AssignmentId()); 44743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4475589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ast_context()->ReturnValue(Pop()); 4476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 44771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4478589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: 4479589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Bailout("assignment to LOOKUP variable"); 4480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("invalid left-hand side in assignment"); 4483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThrow(Throw* expr) { 4488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 4489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 4490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 4491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't optimize functions with invalid left-hand sides in 4492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // assignments, count operations, or for-in. Consequently throw can 4493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // currently only occur in an effect context. 4494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ast_context()->IsEffect()); 4495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->exception())); 4496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 44973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 4498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = environment()->Pop(); 44993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HThrow* instr = new(zone()) HThrow(context, value); 4500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 45011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(instr); 45021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddSimulate(expr->id()); 45038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch current_block()->FinishExit(new(zone()) HAbnormalExit); 4504e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 4505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 4509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr, 4510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> type, 4511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup, 4512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool smi_and_map_check) { 4513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (smi_and_map_check) { 45148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); 45153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckMap(object, type, NULL, 45163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS)); 4517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = lookup->GetLocalFieldIndexFromMap(*type); 4520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (index < 0) { 4521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Negative property indices are in-object properties, indexed 4522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // from the end of the fixed part of the object. 4523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = (index * kPointerSize) + type->instance_size(); 45248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HLoadNamedField(object, true, offset); 4525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Non-negative property indices are in the properties array. 4527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = (index * kPointerSize) + FixedArray::kHeaderSize; 45288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HLoadNamedField(object, false, offset); 4529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, 4534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr) { 45353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->IsUninitialized() && !FLAG_always_opt) { 45363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HSoftDeoptimize); 45373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->MarkAsDeoptimizing(); 45383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(expr->key()->IsPropertyName()); 4540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Object> name = expr->key()->AsLiteral()->handle(); 4541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 45428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HLoadNamedGeneric(context, obj, name); 4543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, 4547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr, 4548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map, 4549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name) { 45503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 4551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->LookupInDescriptors(NULL, *name, &lookup); 45523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup.IsFound() && lookup.type() == FIELD) { 4553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return BuildLoadNamedField(obj, 4554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr, 4555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map, 4556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &lookup, 4557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true); 45583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) { 45598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(obj)); 45603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckMap(obj, map, NULL, 45613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS)); 4562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); 45638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HConstant(function, Representation::Tagged()); 4564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return BuildLoadNamedGeneric(obj, expr); 4566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 4571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key) { 4572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 45738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HLoadKeyedGeneric(context, object, key); 4574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 45773fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHInstruction* HGraphBuilder::BuildExternalArrayElementAccess( 45783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* external_elements, 45793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* checked_key, 45803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* val, 4581589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind, 45823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_store) { 45833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_store) { 45843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(val != NULL); 45853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 4586589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: { 45873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch val = AddInstruction(new(zone()) HClampToUint8(val)); 45883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 45893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4590589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 4591589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 4592589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 4593589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 4594589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 4595589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: { 45963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!val->representation().IsInteger32()) { 45973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch val = AddInstruction(new(zone()) HChange( 45983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch val, 45993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Representation::Integer32(), 46003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch true, // Truncate to int32. 46013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch false)); // Don't deoptimize undefined (irrelevant here). 46023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 46033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 46043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4605589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 4606589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 46073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 46083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 4609589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 4610589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 4611589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 4612589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 46133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch UNREACHABLE(); 46143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 46153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 46163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return new(zone()) HStoreKeyedSpecializedArrayElement( 46173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch external_elements, checked_key, val, elements_kind); 46183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 46193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(val == NULL); 46203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return new(zone()) HLoadKeyedSpecializedArrayElement( 46213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch external_elements, checked_key, elements_kind); 46223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 46233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 46243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 46263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, 46273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* checked_key, 46283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* val, 46293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind elements_kind, 46303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_store) { 46313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_store) { 46323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(val != NULL); 46333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch (elements_kind) { 46343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_DOUBLE_ELEMENTS: 46353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return new(zone()) HStoreKeyedFastDoubleElement( 46363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements, checked_key, val); 46373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 46383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Smi-only arrays need a smi check. 46393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckSmi(val)); 46403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Fall through. 46413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_ELEMENTS: 46423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return new(zone()) HStoreKeyedFastElement( 46433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements, checked_key, val, elements_kind); 46443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch default: 46453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 46463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return NULL; 46473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 46483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 46493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // It's an element load (!is_store). 46503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_DOUBLE_ELEMENTS) { 46513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key); 46523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS. 46533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return new(zone()) HLoadKeyedFastElement(elements, checked_key); 46543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 46553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 46563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 46573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 46583fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, 46593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* key, 46603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* val, 46613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map, 46623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_store) { 4663592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); 46643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool fast_smi_only_elements = map->has_fast_smi_only_elements(); 46653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool fast_elements = map->has_fast_elements(); 466669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 46673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_store && (fast_elements || fast_smi_only_elements)) { 466869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch AddInstruction(new(zone()) HCheckMap( 466969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch elements, isolate()->factory()->fixed_array_map())); 467069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 46719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block HInstruction* length = NULL; 46727d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch HInstruction* checked_key = NULL; 46733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (map->has_external_array_elements()) { 467469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 46753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 46763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HLoadExternalArrayPointer* external_elements = 46773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HLoadExternalArrayPointer(elements); 46783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(external_elements); 46793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return BuildExternalArrayElementAccess(external_elements, checked_key, 46803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch val, map->elements_kind(), is_store); 46813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 46823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(fast_smi_only_elements || 46833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fast_elements || 46843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->has_fast_double_elements()); 46853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (map->instance_type() == JS_ARRAY_TYPE) { 468669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch length = AddInstruction(new(zone()) HJSArrayLength(object, mapcheck)); 46879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 468869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 46899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 469069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 46913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return BuildFastElementAccess(elements, checked_key, val, 46923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->elements_kind(), is_store); 4693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 46963fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHValue* HGraphBuilder::HandlePolymorphicElementAccess(HValue* object, 46973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* key, 46983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* val, 46993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Expression* prop, 47003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int ast_id, 47013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int position, 47023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_store, 47033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool* has_side_effects) { 47043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch *has_side_effects = false; 47058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); 470669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SmallMapList* maps = prop->GetReceiverTypes(); 47073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool todo_external_array = false; 47083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4709589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch static const int kNumElementTypes = kElementsKindCount; 47103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool type_todo[kNumElementTypes]; 47113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < kNumElementTypes; ++i) { 47123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch type_todo[i] = false; 47133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 47143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Elements_kind transition support. 47163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList transition_target(maps->length()); 47173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Collect possible transition targets. 47183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList possible_transitioned_maps(maps->length()); 4719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (int i = 0; i < maps->length(); ++i) { 47203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map = maps->at(i); 47213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind elements_kind = map->elements_kind(); 47223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_DOUBLE_ELEMENTS || 47233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_kind == FAST_ELEMENTS) { 47243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch possible_transitioned_maps.Add(map); 47253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 47263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 47273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get transition target for each map (NULL == no transition). 47283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < maps->length(); ++i) { 47293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map = maps->at(i); 47303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transitioned_map = 47313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch map->FindTransitionedMap(&possible_transitioned_maps); 47323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch transition_target.Add(transitioned_map); 47333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 47343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int num_untransitionable_maps = 0; 47363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> untransitionable_map; 47373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < maps->length(); ++i) { 47383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map = maps->at(i); 47393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(map->IsMap()); 47403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition_target.at(i).is_null()) { 47413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HTransitionElementsKind( 47423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, map, transition_target.at(i))); 47433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 47443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch type_todo[map->elements_kind()] = true; 47453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { 47463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch todo_external_array = true; 47473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 47483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch num_untransitionable_maps++; 47493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch untransitionable_map = map; 47503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 47513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 47523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If only one map is left after transitioning, handle this case 47543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // monomorphically. 47553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (num_untransitionable_maps == 1) { 47563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* instr = NULL; 47573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (untransitionable_map->has_slow_elements_kind()) { 47583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 47593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : BuildLoadKeyedGeneric(object, key)); 47603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 47613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = AddInstruction(BuildMonomorphicElementAccess( 47623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, key, val, untransitionable_map, is_store)); 47633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 47643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *has_side_effects |= instr->HasObservableSideEffects(); 47653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->set_position(position); 47663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return is_store ? NULL : instr; 47673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 47683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 47693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(HCheckInstanceType::NewIsSpecObject(object)); 47703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* join = graph()->CreateBasicBlock(); 47713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* elements_kind_instr = 47733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HElementsKind(object)); 477469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HCompareConstantEqAndBranch* elements_kind_branch = NULL; 477569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 47763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HLoadExternalArrayPointer* external_elements = NULL; 47773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* checked_key = NULL; 47783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS, 47803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS are handled before external 47813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // arrays. 47823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 47833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 47843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 47853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 47863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 47873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; 4788589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind <= LAST_ELEMENTS_KIND; 4789589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind = ElementsKind(elements_kind + 1)) { 47903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // After having handled FAST_ELEMENTS, FAST_SMI_ONLY_ELEMENTS, 47913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS, we need to add some code 47923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // that's executed for all external array cases. 4793589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch STATIC_ASSERT(LAST_EXTERNAL_ARRAY_ELEMENTS_KIND == 4794589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch LAST_ELEMENTS_KIND); 4795589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND 47963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch && todo_external_array) { 47973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* length = 479869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 47993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 48003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch external_elements = new(zone()) HLoadExternalArrayPointer(elements); 48013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(external_elements); 48023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 48033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (type_todo[elements_kind]) { 48043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* if_true = graph()->CreateBasicBlock(); 48053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* if_false = graph()->CreateBasicBlock(); 480669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch elements_kind_branch = new(zone()) HCompareConstantEqAndBranch( 480769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch elements_kind_instr, elements_kind, Token::EQ_STRICT); 480869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch elements_kind_branch->SetSuccessorAt(0, if_true); 480969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch elements_kind_branch->SetSuccessorAt(1, if_false); 481069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch current_block()->Finish(elements_kind_branch); 48113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 48123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_current_block(if_true); 48133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* access; 48143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS || 48153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_kind == FAST_ELEMENTS || 4816589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind == FAST_DOUBLE_ELEMENTS) { 48173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_store && elements_kind != FAST_DOUBLE_ELEMENTS) { 481869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch AddInstruction(new(zone()) HCheckMap( 481969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch elements, isolate()->factory()->fixed_array_map(), 482069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch elements_kind_branch)); 482169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch } 48223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(jkummerow): The need for these two blocks could be avoided 48233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in one of two ways: 48243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // (1) Introduce ElementsKinds for JSArrays that are distinct from 48253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // those for fast objects. 48263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // (2) Put the common instructions into a third "join" block. This 48273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // requires additional AST IDs that we can deopt to from inside 48283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // that join block. They must be added to the Property class (when 48293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // it's a keyed property) and registered in the full codegen. 48303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* if_jsarray = graph()->CreateBasicBlock(); 48313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBasicBlock* if_fastobject = graph()->CreateBasicBlock(); 48323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HHasInstanceTypeAndBranch* typecheck = 48333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HHasInstanceTypeAndBranch(object, JS_ARRAY_TYPE); 48343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch typecheck->SetSuccessorAt(0, if_jsarray); 48353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch typecheck->SetSuccessorAt(1, if_fastobject); 48363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->Finish(typecheck); 48373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 48383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_current_block(if_jsarray); 48393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* length; 48403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck)); 48413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 48423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch access = AddInstruction(BuildFastElementAccess( 48433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements, checked_key, val, elements_kind, is_store)); 48443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!is_store) { 48453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Push(access); 48463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 48473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 48483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *has_side_effects |= access->HasObservableSideEffects(); 48493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (position != -1) { 48503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch access->set_position(position); 48513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 48523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if_jsarray->Goto(join); 48533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 48543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_current_block(if_fastobject); 485569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch length = AddInstruction(new(zone()) HFixedArrayBaseLength(elements)); 48563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 48573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch access = AddInstruction(BuildFastElementAccess( 48583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements, checked_key, val, elements_kind, is_store)); 4859589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == DICTIONARY_ELEMENTS) { 48603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_store) { 48613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch access = AddInstruction(BuildStoreKeyedGeneric(object, key, val)); 48623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 48633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch access = AddInstruction(BuildLoadKeyedGeneric(object, key)); 48643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 48653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { // External array elements. 48663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch access = AddInstruction(BuildExternalArrayElementAccess( 48673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch external_elements, checked_key, val, elements_kind, is_store)); 48683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 48693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *has_side_effects |= access->HasObservableSideEffects(); 48703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch access->set_position(position); 48713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!is_store) { 48723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Push(access); 48733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 48743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->Goto(join); 48753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_current_block(if_false); 48763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 48773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 48783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 48793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Deopt if none of the cases matched. 48803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); 48813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch join->SetJoinId(ast_id); 48823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch set_current_block(join); 48833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return is_store ? NULL : Pop(); 48841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 48851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 48861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 48873fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHValue* HGraphBuilder::HandleKeyedElementAccess(HValue* obj, 48883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* key, 48893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* val, 48903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Expression* expr, 48913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int ast_id, 48923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int position, 48933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_store, 48943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool* has_side_effects) { 48953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(!expr->IsPropertyName()); 48963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = NULL; 48973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (expr->IsMonomorphic()) { 48983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map = expr->GetMonomorphicReceiverType(); 48993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (map->has_slow_elements_kind()) { 49003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 49013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : BuildLoadKeyedGeneric(obj, key); 49023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 49033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckNonSmi(obj)); 49043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store); 49053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 49063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else if (expr->GetReceiverTypes() != NULL && 49073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch !expr->GetReceiverTypes()->is_empty()) { 49083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return HandlePolymorphicElementAccess( 49093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch obj, key, val, expr, ast_id, position, is_store, has_side_effects); 49103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 49113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_store) { 49123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr = BuildStoreKeyedGeneric(obj, key, val); 49133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 49143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr = BuildLoadKeyedGeneric(obj, key); 49158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 49168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 49173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr->set_position(position); 49183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(instr); 49193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *has_side_effects = instr->HasObservableSideEffects(); 49203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return instr; 49218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 49228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 49238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 4924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 4925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key, 4926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value) { 4927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 49288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HStoreKeyedGeneric( 49298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch context, 49308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch object, 49318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch key, 49328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch value, 49333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_strict_mode_flag()); 4934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryArgumentsAccess(Property* expr) { 4937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = expr->obj()->AsVariableProxy(); 4938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (proxy == NULL) return false; 4939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!proxy->var()->IsStackAllocated()) return false; 4940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 4941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 494442effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // Our implementation of arguments (based on this stack frame or an 494542effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // adapter below it) does not work for inlined functions. 494642effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch if (function_state()->outer() != NULL) { 494742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch Bailout("arguments access in inlined function"); 494842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch return true; 494942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch } 495042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch 4951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* result = NULL; 4952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->key()->IsPropertyName()) { 4953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 4954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!name->IsEqualTo(CStrVector("length"))) return false; 49558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 49568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch result = new(zone()) HArgumentsLength(elements); 4957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Push(graph()->GetArgumentsObject()); 4959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(expr->key()); 4960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return true; 4961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 4962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); // Arguments object. 49638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 49648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* length = AddInstruction( 49658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HArgumentsLength(elements)); 49667d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch HInstruction* checked_key = 49677d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch AddInstruction(new(zone()) HBoundsCheck(key, length)); 49687d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch result = new(zone()) HAccessArgumentsAt(elements, length, checked_key); 4969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 4971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitProperty(Property* expr) { 4976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 4977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 4978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 4979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->RecordTypeFeedback(oracle()); 4980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (TryArgumentsAccess(expr)) return; 4982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->obj())); 4984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 49863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->AsProperty()->IsArrayLength()) { 4987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* array = Pop(); 49888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(array)); 498969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HInstruction* mapcheck = 499069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch AddInstruction(HCheckInstanceType::NewIsJSArray(array)); 499169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch instr = new(zone()) HJSArrayLength(array, mapcheck); 49929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 49931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (expr->IsStringLength()) { 49941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* string = Pop(); 49958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(string)); 4996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(HCheckInstanceType::NewIsString(string)); 49978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HStringLength(string); 499844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (expr->IsStringAccess()) { 4999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->key())); 500044f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* index = Pop(); 500144f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* string = Pop(); 50023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 50033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharCodeAt* char_code = 50043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BuildStringCharCodeAt(context, string, index); 500544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(char_code); 50063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr = new(zone()) HStringCharFromCode(context, char_code); 50071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 50089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else if (expr->IsFunctionPrototype()) { 50099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block HValue* function = Pop(); 50108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(function)); 50118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HLoadFunctionPrototype(function); 5012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (expr->key()->IsPropertyName()) { 5014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 501569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SmallMapList* types = expr->GetReceiverTypes(); 5016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Pop(); 5018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->IsMonomorphic()) { 5019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = BuildLoadNamed(obj, expr, types->first(), name); 5020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (types != NULL && types->length() > 1) { 50218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(obj)); 50223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 50233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr = new(zone()) HLoadNamedFieldPolymorphic(context, obj, types, name); 5024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = BuildLoadNamedGeneric(obj, expr); 5026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->key())); 5030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 5032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Pop(); 50333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 50343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool has_side_effects = false; 50353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* load = HandleKeyedElementAccess( 50363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch obj, key, NULL, expr, expr->id(), expr->position(), 50373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch false, // is_store 50383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &has_side_effects); 50393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (has_side_effects) { 50403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (ast_context()->IsEffect()) { 50413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddSimulate(expr->id()); 50423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 50433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Push(load); 50443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddSimulate(expr->id()); 50453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Drop(1); 50463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 50473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 50483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(load); 5049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 50513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 5052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddCheckConstantFunction(Call* expr, 5056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver, 5057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> receiver_map, 5058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool smi_and_map_check) { 5059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Constant functions have the nice property that the map will change if they 5060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // are overwritten. Therefore it is enough to check the map of the holder and 5061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // its prototypes. 5062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (smi_and_map_check) { 50638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(receiver)); 50643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckMap(receiver, receiver_map, NULL, 50653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS)); 5066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!expr->holder().is_null()) { 50688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckPrototypeMaps( 5069b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<JSObject>(JSObject::cast(receiver_map->prototype())), 5070b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch expr->holder())); 5071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, 5076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver, 507769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SmallMapList* types, 5078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name) { 5079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(ager): We should recognize when the prototype chains for different 5080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // maps are identical. In that case we can avoid repeatedly generating the 5081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // same prototype map checks. 508244f0eee88ff00398ff7f715fab053374d808c90dSteve Block int argument_count = expr->arguments()->length() + 1; // Includes receiver. 508344f0eee88ff00398ff7f715fab053374d808c90dSteve Block int count = 0; 508444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* join = NULL; 508544f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) { 5086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = types->at(i); 5087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->ComputeTarget(map, name)) { 508844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (count == 0) { 50898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Only needed once. 50908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(receiver)); 509144f0eee88ff00398ff7f715fab053374d808c90dSteve Block join = graph()->CreateBasicBlock(); 509244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 509344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ++count; 509444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* if_true = graph()->CreateBasicBlock(); 509544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* if_false = graph()->CreateBasicBlock(); 50968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCompareMap* compare = 50978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCompareMap(receiver, map, if_true, if_false); 509844f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->Finish(compare); 509944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 510044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(if_true); 5101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddCheckConstantFunction(expr, receiver, map, false); 5102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 5103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Trying to inline the polymorphic call to %s\n", 5104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *name->ToCString()); 5105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 51063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { 5107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Trying to inline will signal that we should bailout from the 5108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // entire compilation by setting stack overflow on the visitor. 5109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasStackOverflow()) return; 5110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 5111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HCallConstantFunction* call = 51128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallConstantFunction(expr->target(), argument_count); 5113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 51141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PreProcessCall(call); 511544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(call); 511644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!ast_context()->IsEffect()) Push(call); 5117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 511844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 511944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (current_block() != NULL) current_block()->Goto(join); 512044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(if_false); 5121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 512444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Finish up. Unconditionally deoptimize if we've handled all the maps we 512544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // know about and do not want to handle ones we've never seen. Otherwise 512644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // use a generic IC. 512744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 5128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current_block()->FinishExitWithDeoptimization(HDeoptimize::kNoUses); 512944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 5130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 51318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); 5132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 51331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PreProcessCall(call); 5134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 513544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (join != NULL) { 513644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(call); 513744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!ast_context()->IsEffect()) Push(call); 513844f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->Goto(join); 513944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 51403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 51419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 5142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 514344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 514444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We assume that control flow is always live after an expression. So 514544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // even without predecessors to the join block, we set it as the exit 514644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // block and continue by adding instructions there. 514744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(join != NULL); 514844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (join->HasPredecessor()) { 5149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(join); 515044f0eee88ff00398ff7f715fab053374d808c90dSteve Block join->SetJoinId(expr->id()); 51513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); 5152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 5153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(NULL); 515444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 5155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::TraceInline(Handle<JSFunction> target, 5159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<JSFunction> caller, 5160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const char* reason) { 5161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_trace_inlining) { 5162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SmartArrayPointer<char> target_name = 5163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch target->shared()->DebugName()->ToCString(); 5164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch SmartArrayPointer<char> caller_name = 5165589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch caller->shared()->DebugName()->ToCString(); 5166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (reason == NULL) { 5167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Inlined %s called from %s.\n", *target_name, *caller_name); 5168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 5169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF("Did not inline %s called from %s (%s).\n", 5170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch *target_name, *caller_name, reason); 5171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 5172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 51763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::TryInline(CallKind call_kind, 51773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> target, 51783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ZoneList<Expression*>* arguments, 51793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* receiver, 51803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int ast_id, 51813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int return_id, 51823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ReturnHandlingFlag return_handling) { 5183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!FLAG_use_inlining) return false; 5184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Precondition: call is monomorphic and we have found a target with the 5186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // appropriate arity. 5187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<JSFunction> caller = info()->closure(); 5188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<SharedFunctionInfo> target_shared(target->shared()); 5189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do a quick check on source code length to avoid parsing large 5191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // inlining candidates. 51923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if ((FLAG_limit_inlining && target_shared->SourceSize() > kMaxSourceSize) 51933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch || target_shared->SourceSize() > kUnlimitedMaxSourceSize) { 5194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, "target text too big"); 5195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 5196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Target must be inlineable. 5199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!target->IsInlineable()) { 5200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, "target not inlineable"); 5201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 5202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 52033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (target_shared->dont_inline() || target_shared->dont_optimize()) { 52043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TraceInline(target, caller, "target contains unsupported syntax [early]"); 52053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 52063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 52083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int nodes_added = target_shared->ast_node_count(); 52093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) || 52103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch nodes_added > kUnlimitedMaxInlinedSize) { 52113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TraceInline(target, caller, "target AST is too large [early]"); 52123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 52133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 52143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 52153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#if !defined(V8_TARGET_ARCH_IA32) 52163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Target must be able to use caller's context. 5217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CompilationInfo* outer_info = info(); 5218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (target->context() != outer_info->closure()->context() || 5219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_info->scope()->contains_with() || 5220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_info->scope()->num_heap_slots() > 0) { 5221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, "target requires context change"); 5222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 5223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 52243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 52253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 52278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Don't inline deeper than kMaxInliningLevels calls. 5228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* env = environment(); 52298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int current_level = 1; 52308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch while (env->outer() != NULL) { 52318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (current_level == Compiler::kMaxInliningLevels) { 5232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, "inline depth limit reached"); 52338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return false; 52348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 52353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (env->outer()->frame_type() == JS_FUNCTION) { 52363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_level++; 52373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 52388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch env = env->outer(); 5239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 5240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Don't inline recursive functions. 52423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (FunctionState* state = function_state(); 52433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch state != NULL; 52443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch state = state->outer()) { 52453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (state->compilation_info()->closure()->shared() == *target_shared) { 52463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TraceInline(target, caller, "target is recursive"); 52473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 52483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 5250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't want to add more than a certain number of nodes from inlining. 52523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if ((FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) || 52533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inlined_count_ > kUnlimitedMaxInlinedNodes) { 5254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, "cumulative AST node limit reached"); 5255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 5256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Parse and allocate variables. 5259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CompilationInfo target_info(target); 52603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!ParserApi::Parse(&target_info, kNoParsingFlags) || 5261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !Scope::Analyze(&target_info)) { 526244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (target_info.isolate()->has_pending_exception()) { 5263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Parse or scope error, never optimize this function. 52641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SetStackOverflow(); 52653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch target_shared->DisableOptimization(); 52661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 5267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, "parse failure"); 5268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 5269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 5270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 5271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (target_info.scope()->num_heap_slots() > 0) { 5272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, "target has context-allocated variables"); 5273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 5274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FunctionLiteral* function = target_info.function(); 5276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 52773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The following conditions must be checked again after re-parsing, because 52783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // earlier the information might not have been complete due to lazy parsing. 52793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch nodes_added = function->ast_node_count(); 52803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) || 52813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch nodes_added > kUnlimitedMaxInlinedSize) { 52823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TraceInline(target, caller, "target AST is too large [late]"); 5283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 5284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 52853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AstProperties::Flags* flags(function->flags()); 52863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) { 52873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TraceInline(target, caller, "target contains unsupported syntax [late]"); 528885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch return false; 5289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 52913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the function uses the arguments object check that inlining of functions 52923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // with arguments object is enabled and the arguments-variable is 52933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // stack allocated. 52943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->scope()->arguments() != NULL) { 52953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!FLAG_inline_arguments) { 52963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TraceInline(target, caller, "target uses arguments object"); 52973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 52983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 52993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 53003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!function->scope()->arguments()->IsStackAllocated()) { 53013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TraceInline(target, 53023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch caller, 53033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch "target uses non-stackallocated arguments object"); 53043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 53053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 53063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 53073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 53083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // All declarations must be inlineable. 53093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ZoneList<Declaration*>* decls = target_info.scope()->declarations(); 53103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int decl_count = decls->length(); 53113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < decl_count; ++i) { 53123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (!decls->at(i)->IsInlineable()) { 53133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch TraceInline(target, caller, "target has non-trivial declaration"); 53143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return false; 53153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 53163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 5317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Generate the deoptimization data for the unoptimized version of 5319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the target function if we don't already have it. 5320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!target_shared->has_deoptimization_support()) { 5321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Note that we compile here using the same AST that we will use for 5322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // generating the optimized inline code. 5323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch target_info.EnableDeoptimizationSupport(); 5324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!FullCodeGenerator::MakeCode(&target_info)) { 5325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, "could not generate deoptimization info"); 5326e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 5327e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 53283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (target_shared->scope_info() == ScopeInfo::Empty()) { 53293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // The scope info might not have been set if a lazily compiled 53303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // function is inlined before being called for the first time. 53313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<ScopeInfo> target_scope_info = 53323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScopeInfo::Create(target_info.scope()); 53333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch target_shared->set_scope_info(*target_scope_info); 53343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 5335e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch target_shared->EnableDeoptimizationSupport(*target_info.code()); 5336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, 5337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch &target_info, 5338e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch target_shared); 5339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5341e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // ---------------------------------------------------------------- 53423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // After this point, we've made a decision to inline this function (so 53433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // TryInline should always return true). 53443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Save the pending call context and type feedback oracle. Set up new ones 5346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // for the inlined function. 5347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(target_shared->has_deoptimization_support()); 5348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TypeFeedbackOracle target_oracle( 5349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<Code>(target_shared->code()), 53503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Context>(target->context()->global_context()), 53513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()); 53523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The function state is new-allocated because we need to delete it 53533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in two different places. 53543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FunctionState* target_state = new FunctionState( 53553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch this, &target_info, &target_oracle, return_handling); 5356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 535744f0eee88ff00398ff7f715fab053374d808c90dSteve Block HConstant* undefined = graph()->GetConstantUndefined(); 535844f0eee88ff00398ff7f715fab053374d808c90dSteve Block HEnvironment* inner_env = 5359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch environment()->CopyForInlining(target, 53603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch arguments->length(), 5361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch function, 5362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch undefined, 53633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_kind, 53643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_state()->is_construct()); 53653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef V8_TARGET_ARCH_IA32 53663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // IA32 only, overwrite the caller's context in the deoptimization 53673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // environment with the correct one. 53683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 53693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(kmillikin): implement the same inlining on other platforms so we 53703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // can remove the unsightly ifdefs in this function. 53713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HConstant* context = new HConstant(Handle<Context>(target->context()), 53723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Representation::Tagged()); 53733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(context); 53743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inner_env->BindContext(context); 53753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 53763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddSimulate(return_id); 53773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->UpdateEnvironment(inner_env); 5378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(new(zone()) HEnterInlined(target, 53793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch arguments->length(), 5380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch function, 53813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_kind, 53823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_state()->is_construct(), 53833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function->scope()->arguments())); 53843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If the function uses arguments object create and bind one. 53853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->scope()->arguments() != NULL) { 53863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(function->scope()->arguments()->IsStackAllocated()); 53873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->Bind(function->scope()->arguments(), 53883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch graph()->GetArgumentsObject()); 53893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 53903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitDeclarations(target_info.scope()->declarations()); 539144f0eee88ff00398ff7f715fab053374d808c90dSteve Block VisitStatements(function->body()); 5392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) { 5393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Bail out if the inline function did, as we cannot residualize a call 5394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // instead. 5395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, "inline graph construction failed"); 53963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch target_shared->DisableOptimization(); 5397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inline_bailout_ = true; 53983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch delete target_state; 5399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 5400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Update inlined nodes count. 5403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inlined_count_ += nodes_added; 5404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, NULL); 5406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 540744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (current_block() != NULL) { 54083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Add default return value (i.e. undefined for normals calls or the newly 54093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocated receiver for construct calls) if control can fall off the 54103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // body. In a test context, undefined is false and any JSObject is true. 54113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (call_context()->IsValue()) { 54125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(function_return() != NULL); 54133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* return_value = function_state()->is_construct() 54143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? receiver 54153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : undefined; 54163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->AddLeaveInlined(return_value, 54173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_return(), 54183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_state()->drop_extra()); 54193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (call_context()->IsEffect()) { 54203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(function_return() != NULL); 54213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Goto(function_return(), function_state()->drop_extra()); 5422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 54233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(call_context()->IsTest()); 54243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(inlined_test_context() != NULL); 54253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* target = function_state()->is_construct() 54263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? inlined_test_context()->if_true() 54273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : inlined_test_context()->if_false(); 54283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Goto(target, function_state()->drop_extra()); 5429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Fix up the function exits. 5433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (inlined_test_context() != NULL) { 5434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_true = inlined_test_context()->if_true(); 5435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_false = inlined_test_context()->if_false(); 54363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Pop the return test context from the expression context stack. 54383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ast_context() == inlined_test_context()); 5439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ClearInlinedTestContext(); 54403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch delete target_state; 5441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Forward to the real test context. 5443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (if_true->HasPredecessor()) { 54443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if_true->SetJoinId(ast_id); 5445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 54463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if_true->Goto(true_target, function_state()->drop_extra()); 5447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (if_false->HasPredecessor()) { 54493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if_false->SetJoinId(ast_id); 5450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 54513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if_false->Goto(false_target, function_state()->drop_extra()); 5452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 54543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 5455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (function_return()->HasPredecessor()) { 54573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_return()->SetJoinId(ast_id); 5458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(function_return()); 5459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 5460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(NULL); 5461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 54623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch delete target_state; 546385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch return true; 54645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 54655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 54665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 54673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { 54683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The function call we are inlining is a method call if the call 54693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // is a property call. 54703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = (expr->expression()->AsProperty() == NULL) 54713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? CALL_AS_FUNCTION 54723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : CALL_AS_METHOD; 54733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 54743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return TryInline(call_kind, 54753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->target(), 54763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->arguments(), 54773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NULL, 54783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->id(), 54793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->ReturnId(), 54803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); 54813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 54823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 54833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 54843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) { 54853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return TryInline(CALL_AS_FUNCTION, 54863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->target(), 54873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->arguments(), 54883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 54893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->id(), 54903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->ReturnId(), 54913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CONSTRUCT_CALL_RETURN); 54923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 54933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 54943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 54953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { 54963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 54973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 54983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch switch (id) { 54993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathRound: 55003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathAbs: 55013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathSqrt: 55023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathLog: 55033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathSin: 55043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathCos: 55053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathTan: 55063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (expr->arguments()->length() == 1) { 55073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* argument = Pop(); 55083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* context = environment()->LookupContext(); 55093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Drop(1); // Receiver. 55103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HUnaryMathOperation* op = 55113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HUnaryMathOperation(context, argument, id); 55123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch op->set_position(expr->position()); 55133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (drop_extra) Drop(1); // Optionally drop the function. 55143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ast_context()->ReturnInstruction(op, expr->id()); 55153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 55163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 55173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 55183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch default: 55193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Not supported for inlining yet. 55203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 55213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 55223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 55233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 55243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 55253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 55263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochbool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, 55273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* receiver, 55283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map, 55293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckType check_type) { 55301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); 5531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Try to inline calls like Math.* as operations in the calling function. 55321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 5533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 5534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length() + 1; // Plus receiver. 5535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (id) { 55361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case kStringCharCodeAt: 553744f0eee88ff00398ff7f715fab053374d808c90dSteve Block case kStringCharAt: 55381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (argument_count == 2 && check_type == STRING_CHECK) { 55391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* index = Pop(); 55401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* string = Pop(); 55413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 55421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!expr->holder().is_null()); 55438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckPrototypeMaps( 55441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK), 55451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block expr->holder())); 55463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharCodeAt* char_code = 55473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BuildStringCharCodeAt(context, string, index); 554844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (id == kStringCharCodeAt) { 554944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ast_context()->ReturnInstruction(char_code, expr->id()); 555044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return true; 555144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 555244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(char_code); 55538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStringCharFromCode* result = 55543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HStringCharFromCode(context, char_code); 55551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ast_context()->ReturnInstruction(result, expr->id()); 55561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return true; 55571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 55581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 5559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathRound: 5560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathFloor: 5561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathAbs: 5562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathSqrt: 5563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathLog: 5564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathSin: 5565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathCos: 55663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathTan: 55671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 55681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddCheckConstantFunction(expr, receiver, receiver_map, true); 5569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* argument = Pop(); 55703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 5571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(1); // Receiver. 55723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HUnaryMathOperation* op = 55733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HUnaryMathOperation(context, argument, id); 5574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch op->set_position(expr->position()); 5575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(op, expr->id()); 5576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 5577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 5579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathPow: 55801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 55811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddCheckConstantFunction(expr, receiver, receiver_map, true); 5582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 5583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 5584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Pop(); // Pop receiver. 55853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 5586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* result = NULL; 5587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Use sqrt() if exponent is 0.5 or -0.5. 5588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 5589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double exponent = HConstant::cast(right)->DoubleValue(); 5590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (exponent == 0.5) { 55913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result = 55923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HUnaryMathOperation(context, left, kMathPowHalf); 5593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (exponent == -0.5) { 5594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* double_one = 55958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HConstant(Handle<Object>(Smi::FromInt(1)), 55968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Representation::Double()); 5597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(double_one); 5598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HUnaryMathOperation* square_root = 55993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HUnaryMathOperation(context, left, kMathPowHalf); 5600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(square_root); 5601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // MathPowHalf doesn't have side effects so there's no need for 5602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // an environment simulation here. 56033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!square_root->HasObservableSideEffects()); 56043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result = new(zone()) HDiv(context, double_one, square_root); 5605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (exponent == 2.0) { 56063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result = new(zone()) HMul(context, left, left); 5607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (right->IsConstant() && 56091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HConstant::cast(right)->HasInteger32Value() && 56101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HConstant::cast(right)->Integer32Value() == 2) { 56113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result = new(zone()) HMul(context, left, left); 5612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 56141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (result == NULL) { 56158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch result = new(zone()) HPower(left, right); 56161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 5617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 5618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 5619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 56213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathRandom: 56223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { 56233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddCheckConstantFunction(expr, receiver, receiver_map, true); 56243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Drop(1); // Receiver. 56253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* context = environment()->LookupContext(); 56263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 56273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(global_object); 56283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HRandom* result = new(zone()) HRandom(global_object); 56293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ast_context()->ReturnInstruction(result, expr->id()); 56303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 56313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 56323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 56333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathMax: 56343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case kMathMin: 56353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 56363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddCheckConstantFunction(expr, receiver, receiver_map, true); 56373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* right = Pop(); 56383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* left = Pop(); 56393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Pop(); // Pop receiver. 56403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 56413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* left_operand = left; 56423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* right_operand = right; 56433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 56443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we do not have two integers, we convert to double for comparison. 56453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!left->representation().IsInteger32() || 56463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !right->representation().IsInteger32()) { 56473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!left->representation().IsDouble()) { 56483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HChange* left_convert = new(zone()) HChange( 56493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch left, 56503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Representation::Double(), 56513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch false, // Do not truncate when converting to double. 56523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch true); // Deoptimize for undefined. 56533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch left_convert->SetFlag(HValue::kBailoutOnMinusZero); 56543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch left_operand = AddInstruction(left_convert); 56553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 56563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!right->representation().IsDouble()) { 56573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HChange* right_convert = new(zone()) HChange( 56583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch right, 56593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Representation::Double(), 56603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch false, // Do not truncate when converting to double. 56613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch true); // Deoptimize for undefined. 56623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch right_convert->SetFlag(HValue::kBailoutOnMinusZero); 56633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch right_operand = AddInstruction(right_convert); 56643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 56653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 56663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 56673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(left_operand->representation().Equals( 56683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch right_operand->representation())); 56693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!left_operand->representation().IsTagged()); 56703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 56713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::Value op = (id == kMathMin) ? Token::LT : Token::GT; 56723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 56733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HCompareIDAndBranch* compare = 56743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCompareIDAndBranch(left_operand, right_operand, op); 56753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare->SetInputRepresentation(left_operand->representation()); 56763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 56773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* return_left = graph()->CreateBasicBlock(); 56783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* return_right = graph()->CreateBasicBlock(); 56793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 56803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare->SetSuccessorAt(0, return_left); 56813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare->SetSuccessorAt(1, return_right); 56823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Finish(compare); 56833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 56843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(return_left); 56853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(left); 56863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(return_right); 56873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The branch above always returns the right operand if either of 56883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // them is NaN, but the spec requires that max/min(NaN, X) = NaN. 56893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We add another branch that checks if the left operand is NaN or not. 56903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (left_operand->representation().IsDouble()) { 56913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If left_operand != left_operand then it is NaN. 56923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HCompareIDAndBranch* compare_nan = new(zone()) HCompareIDAndBranch( 56933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch left_operand, left_operand, Token::EQ); 56943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare_nan->SetInputRepresentation(left_operand->representation()); 56953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* left_is_number = graph()->CreateBasicBlock(); 56963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* left_is_nan = graph()->CreateBasicBlock(); 56973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare_nan->SetSuccessorAt(0, left_is_number); 56983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compare_nan->SetSuccessorAt(1, left_is_nan); 56993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Finish(compare_nan); 57003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(left_is_nan); 57013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(left); 57023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(left_is_number); 57033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(right); 57043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return_right = CreateJoin(left_is_number, left_is_nan, expr->id()); 57053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 57063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(right); 57073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 57083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 57093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* join = CreateJoin(return_left, return_right, expr->id()); 57103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(join); 57113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ast_context()->ReturnValue(Pop()); 57123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 57133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 57143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 5715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 5716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Not yet supported for inlining. 5717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 5718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 5720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryCallApply(Call* expr) { 5724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* callee = expr->expression(); 5725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = callee->AsProperty(); 5726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(prop != NULL); 5727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 572842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { 572942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch return false; 573042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch } 573142effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch Handle<Map> function_map = expr->GetReceiverTypes()->first(); 573242effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch if (function_map->instance_type() != JS_FUNCTION_TYPE || 573342effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch !expr->target()->shared()->HasBuiltinFunctionId() || 573442effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch expr->target()->shared()->builtin_function_id() != kFunctionApply) { 573542effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch return false; 573642effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch } 5737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 573842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch if (info()->scope()->arguments() == NULL) return false; 5739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 5741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (args->length() != 2) return false; 5742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 5744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 5745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* arg_two_value = environment()->Lookup(arg_two->var()); 5746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 5747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Found pattern f.apply(receiver, arguments). 5749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(prop->obj()); 5750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return true; 5751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* function = Top(); 5752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddCheckConstantFunction(expr, function, function_map, true); 5753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Drop(1); 5754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(args->at(0)); 5756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return true; 5757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver = Pop(); 57583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 57593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function_state()->outer() == NULL) { 57603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 57613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* length = 57623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HArgumentsLength(elements)); 57633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* wrapped_receiver = 57643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HWrapReceiver(receiver, function)); 57653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* result = 57663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HApplyArguments(function, 57673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch wrapped_receiver, 57683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch length, 57693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements); 57703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result->set_position(expr->position()); 57713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ast_context()->ReturnInstruction(result, expr->id()); 57723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 57733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 57743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We are inside inlined function and we know exactly what is inside 57753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // arguments object. 57763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* context = environment()->LookupContext(); 57773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 57783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* wrapped_receiver = 57793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HWrapReceiver(receiver, function)); 57803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PushAndAdd(new(zone()) HPushArgument(wrapped_receiver)); 57813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 57823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HEnvironment* arguments_env = environment()->arguments_environment(); 57833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 57843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int parameter_count = arguments_env->parameter_count(); 57853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 1; i < arguments_env->parameter_count(); i++) { 57863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PushAndAdd(new(zone()) HPushArgument(arguments_env->Lookup(i))); 57873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 57883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 57893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInvokeFunction* call = new(zone()) HInvokeFunction( 57903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context, 57913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, 57923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch parameter_count); 57933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Drop(parameter_count); 57943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call->set_position(expr->position()); 57953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ast_context()->ReturnInstruction(call, expr->id()); 57963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 57973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCall(Call* expr) { 5802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 5803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 5804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 5805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* callee = expr->expression(); 5806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length() + 1; // Plus receiver. 5807e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HInstruction* call = NULL; 5808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = callee->AsProperty(); 5810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop != NULL) { 5811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!prop->key()->IsPropertyName()) { 5812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed function call. 58133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_ALIVE(VisitArgument(prop->obj())); 5814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 5816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push receiver and key like the non-optimized code generator expects it. 5817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 5818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver = Pop(); 5819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(key); 5820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(receiver); 5821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 58223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 58253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch call = new(zone()) HCallKeyed(context, key, argument_count); 5826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 58273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Drop(argument_count + 1); // 1 is the key. 58283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 5829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named function call. 5832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); 5833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (TryCallApply(expr)) return; 5835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 5837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 5838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 5840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 584169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SmallMapList* types = expr->GetReceiverTypes(); 5842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 58431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* receiver = 58441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block environment()->ExpressionStackAt(expr->arguments()->length()); 58451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (expr->IsMonomorphic()) { 584669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Handle<Map> receiver_map = (types == NULL || types->is_empty()) 584769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ? Handle<Map>::null() 584869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch : types->first(); 58493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryInlineBuiltinMethodCall(expr, 58503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 58513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_map, 58523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->check_type())) { 58533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_inlining) { 58543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("Inlining builtin "); 58553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->target()->ShortPrint(); 58563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("\n"); 58573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 5858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 5859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 58613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || 58621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block expr->check_type() != RECEIVER_MAP_CHECK) { 58631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // When the target has a custom call IC generator, use the IC, 586444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // because it is likely to generate better code. Also use the IC 586544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // when a primitive receiver check is required. 5866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 58678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall( 58688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallNamed(context, name, argument_count)); 58691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 58701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddCheckConstantFunction(expr, receiver, receiver_map, true); 58711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 58723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryInlineCall(expr)) return; 5873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call = PreProcessCall( 5874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch new(zone()) HCallConstantFunction(expr->target(), 5875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch argument_count)); 58761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 5877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (types != NULL && types->length() > 1) { 5878b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 5879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandlePolymorphicCallNamed(expr, receiver, types, name); 5880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 5881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 58848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall( 58858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallNamed(context, name, argument_count)); 5886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 58893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION); 5890589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 5891589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); 5892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 58933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (proxy != NULL && proxy->var()->is_possibly_eval()) { 58943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Bailout("possible direct call to eval"); 58953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 58963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (global_call) { 5898589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 5899e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bool known_global_function = false; 5900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If there is a global property cell for the name at compile time and 5901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // access check is not enabled we assume that the function will not change 5902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // and generate optimized code for calling the function. 59033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 59048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 59058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (type == kUseCell && 5906e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !info()->global_object()->IsAccessCheckNeeded()) { 5907e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<GlobalObject> global(info()->global_object()); 59088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch known_global_function = expr->ComputeGlobalTarget(global, &lookup); 5909e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 5910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (known_global_function) { 5911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push the global object instead of the global receiver because 5912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // code generated by the full code generator expects it. 5913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 59148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 59151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PushAndAdd(global_object); 5916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 5917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 5919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* function = Pop(); 59208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 5921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Replace the global object with the global receiver. 59238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalReceiver* global_receiver = 59248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HGlobalReceiver(global_object); 5925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Index of the receiver from the top of the expression stack. 5926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const int receiver_index = argument_count - 1; 5927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(global_receiver); 5928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(environment()->ExpressionStackAt(receiver_index)-> 5929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch IsGlobalObject()); 5930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(receiver_index, global_receiver); 5931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 59323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. 59333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_inlining) { 59343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("Inlining builtin "); 59353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->target()->ShortPrint(); 59363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("\n"); 59373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 59383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 59393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 59403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryInlineCall(expr)) return; 59418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), 5942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch argument_count)); 5943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 59453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HGlobalObject* receiver = new(zone()) HGlobalObject(context); 59463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(receiver); 59473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PushAndAdd(new(zone()) HPushArgument(receiver)); 59483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 59503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch call = new(zone()) HCallGlobal(context, var->name(), argument_count); 59513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Drop(argument_count); 5952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 59543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (expr->IsMonomorphic()) { 59553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The function is on the stack in the unoptimized code during 59563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // evaluation of the arguments. 59573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 59583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* function = Top(); 59593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* context = environment()->LookupContext(); 59603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HGlobalObject* global = new(zone()) HGlobalObject(context); 59613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); 59623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(global); 59633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PushAndAdd(receiver); 59643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 59653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 59663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 59673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. 59683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_inlining) { 59693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("Inlining builtin "); 59703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->target()->ShortPrint(); 59713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("\n"); 59723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 59733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 59743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 59753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 59763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryInlineCall(expr, true)) { // Drop function from environment. 59773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 59783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 59793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call = PreProcessCall(new(zone()) HInvokeFunction(context, 59803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, 59813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch argument_count)); 59823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Drop(1); // The function. 59833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 59843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 59863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 59873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* function = Top(); 5988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 59898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 59903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object); 59911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(global_object); 59923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(receiver); 59933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PushAndAdd(new(zone()) HPushArgument(receiver)); 59943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 59963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call = new(zone()) HCallFunction(context, function, argument_count); 59973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Drop(argument_count + 1); 5998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 60023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 6003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 60063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Checks whether allocation using the given constructor can be inlined. 60073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsAllocationInlineable(Handle<JSFunction> constructor) { 60083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return constructor->has_initial_map() && 60093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch constructor->initial_map()->instance_type() == JS_OBJECT_TYPE; 60103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 60113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 60123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallNew(CallNew* expr) { 6014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 60173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->RecordTypeFeedback(oracle()); 60183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int argument_count = expr->arguments()->length() + 1; // Plus constructor. 6019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 60201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 60213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_inline_construct && 60223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->IsMonomorphic() && 60233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch IsAllocationInlineable(expr->target())) { 60243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The constructor function is on the stack in the unoptimized code 60253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // during evaluation of the arguments. 60263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 60273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* function = Top(); 60283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 60293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> constructor = expr->target(); 60303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* check = AddInstruction( 60313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCheckFunction(function, constructor)); 60323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 60333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Force completion of inobject slack tracking before generating 60343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allocation code to finalize instance size. 60353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { 60363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch constructor->shared()->CompleteInobjectSlackTracking(); 60373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 60383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 60393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Replace the constructor function with a newly allocated receiver. 60403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* receiver = new(zone()) HAllocateObject(context, constructor); 60413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Index of the receiver from the top of the expression stack. 60423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int receiver_index = argument_count - 1; 60433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(receiver); 60443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(environment()->ExpressionStackAt(receiver_index) == function); 60453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->SetExpressionStackAt(receiver_index, receiver); 60463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 60473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (TryInlineConstruct(expr, receiver)) return; 60483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 60493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(mstarzinger): For now we remove the previous HAllocateObject and 60503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // add HPushArgument for the arguments in case inlining failed. What we 60513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // actually should do is emit HInvokeFunction on the constructor instead 60523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of using HCallNew as a fallback. 60533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver->DeleteAndReplaceWith(NULL); 60543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch check->DeleteAndReplaceWith(NULL); 60553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch environment()->SetExpressionStackAt(receiver_index, function); 60563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* call = PreProcessCall( 60573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCallNew(context, function, argument_count)); 60583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call->set_position(expr->position()); 60593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 60603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 60613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The constructor function is both an operand to the instruction and an 60623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // argument to the construct call. 60633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* constructor = NULL; 60643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(constructor = VisitArgument(expr->expression())); 60653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 60663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* call = 60673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCallNew(context, constructor, argument_count); 60683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Drop(argument_count); 60693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call->set_position(expr->position()); 60703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 60713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 6072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for generating inlined runtime functions. 6076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Lookup table for generators for runtime calls that are generated inline. 6078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Elements of the table are member pointers to functions of HGraphBuilder. 6079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 6080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &HGraphBuilder::Generate##Name, 6081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst HGraphBuilder::InlineFunctionGenerator 6083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder::kInlineFunctionGenerators[] = { 6084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 6085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 6086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 6087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef INLINE_FUNCTION_GENERATOR_ADDRESS 6088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 6091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 6094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->is_jsruntime()) { 6095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("call to a JavaScript runtime function"); 6096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 609844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Runtime::Function* function = expr->function(); 6099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(function != NULL); 6100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (function->intrinsic_type == Runtime::INLINE) { 6101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(expr->name()->length() > 0); 6102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(expr->name()->Get(0) == '_'); 6103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Call to an inline function. 6104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int lookup_index = static_cast<int>(function->function_id) - 6105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(Runtime::kFirstInlineFunction); 6106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(lookup_index >= 0); 6107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(static_cast<size_t>(lookup_index) < 6108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ARRAY_SIZE(kInlineFunctionGenerators)); 6109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 6110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Call the inline code generator using the pointer-to-member. 6112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (this->*generator)(expr); 6113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(function->intrinsic_type == Runtime::RUNTIME); 6115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 6116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 61173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 6118e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<String> name = expr->name(); 6119e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int argument_count = expr->arguments()->length(); 61208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallRuntime* call = 61213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HCallRuntime(context, name, function, argument_count); 6122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(RelocInfo::kNoPosition); 6123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(argument_count); 61243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 6125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 6130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 6133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (expr->op()) { 6134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::DELETE: return VisitDelete(expr); 6135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::VOID: return VisitVoid(expr); 6136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::TYPEOF: return VisitTypeof(expr); 6137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::ADD: return VisitAdd(expr); 6138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: return VisitSub(expr); 6139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_NOT: return VisitBitNot(expr); 6140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::NOT: return VisitNot(expr); 6141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: UNREACHABLE(); 6142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitDelete(UnaryOperation* expr) { 6146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Property* prop = expr->expression()->AsProperty(); 6147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 6148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (prop != NULL) { 614969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 615069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 615169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HValue* key = Pop(); 615269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HValue* obj = Pop(); 615369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HValue* context = environment()->LookupContext(); 615469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); 615569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6156589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL) { 6157589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 6158589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 6159589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Bailout("delete with global variable"); 6160589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (var->IsStackAllocated() || var->IsContextSlot()) { 6161589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Result of deleting non-global variables is false. 'this' is not 6162589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // really a variable, though we implement it as one. The 6163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // subexpression does not have side effects. 6164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* value = var->is_this() 6165589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ? graph()->GetConstantTrue() 6166589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch : graph()->GetConstantFalse(); 6167589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ast_context()->ReturnValue(value); 6168589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 6169589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Bailout("delete with non-global variable"); 6170589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 6171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6172589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Result of deleting non-property, non-variable reference is true. 6173589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Evaluate the subexpression for side effects. 6174589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CHECK_ALIVE(VisitForEffect(expr->expression())); 6175589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ast_context()->ReturnValue(graph()->GetConstantTrue()); 6176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 617944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitVoid(UnaryOperation* expr) { 6181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForEffect(expr->expression())); 61823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 6183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitTypeof(UnaryOperation* expr) { 6187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForTypeOf(expr->expression())); 6188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = Pop(); 61893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 61903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = new(zone()) HTypeof(context, value); 61913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitAdd(UnaryOperation* expr) { 6196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 6197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = Pop(); 61983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 61993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = 62003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HMul(context, value, graph_->GetConstant1()); 62013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitSub(UnaryOperation* expr) { 6206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 6207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = Pop(); 62083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 62093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = 62103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HMul(context, value, graph_->GetConstantMinus1()); 6211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TypeInfo info = oracle()->UnaryType(expr); 62123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (info.IsUninitialized()) { 62133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HSoftDeoptimize); 62143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->MarkAsDeoptimizing(); 62153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch info = TypeInfo::Unknown(); 62163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation rep = ToRepresentation(info); 6218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceRepresentation(expr->op(), info, instr, rep); 6219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->AssumeRepresentation(rep); 62203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitBitNot(UnaryOperation* expr) { 6225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 6226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = Pop(); 62273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch TypeInfo info = oracle()->UnaryType(expr); 62283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (info.IsUninitialized()) { 62293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HSoftDeoptimize); 62303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->MarkAsDeoptimizing(); 62313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HInstruction* instr = new(zone()) HBitNot(value); 62333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitNot(UnaryOperation* expr) { 6238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (ast_context()->IsTest()) { 6239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TestContext* context = TestContext::cast(ast_context()); 6240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForControl(expr->expression(), 6241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context->if_false(), 6242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context->if_true()); 6243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return; 6244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (ast_context()->IsEffect()) { 6247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForEffect(expr->expression()); 6248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return; 6249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(ast_context()->IsValue()); 6252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* materialize_false = graph()->CreateBasicBlock(); 6253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* materialize_true = graph()->CreateBasicBlock(); 6254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->expression(), 6255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch materialize_false, 6256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch materialize_true)); 6257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (materialize_false->HasPredecessor()) { 62593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch materialize_false->SetJoinId(expr->MaterializeFalseId()); 6260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(materialize_false); 6261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Push(graph()->GetConstantFalse()); 626244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 6263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch materialize_false = NULL; 6264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (materialize_true->HasPredecessor()) { 62673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch materialize_true->SetJoinId(expr->MaterializeTrueId()); 6268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(materialize_true); 6269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Push(graph()->GetConstantTrue()); 6270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch materialize_true = NULL; 6272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* join = 6275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CreateJoin(materialize_false, materialize_true, expr->id()); 6276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(join); 62773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (join != NULL) return ast_context()->ReturnValue(Pop()); 6278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, 6282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CountOperation* expr) { 6283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The input to the count operation is on top of the expression stack. 6284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TypeInfo info = oracle()->IncrementType(expr); 6285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation rep = ToRepresentation(info); 6286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (rep.IsTagged()) { 6287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rep = Representation::Integer32(); 6288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (returns_original_input) { 6291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We need an explicit HValue representing ToNumber(input). The 6292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // actual HChange instruction we need is (sometimes) added in a later 6293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // phase, so it is not available now to be used as an input to HAdd and 6294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // as the return value. 6295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); 6296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(number_input); 6297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Push(number_input); 6298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6300257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The addition has no side effects, so we do not need 6301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // to simulate the expression stack after this instruction. 6302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Any later failures deopt to the load of the input or earlier. 6303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HConstant* delta = (expr->op() == Token::INC) 6304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? graph_->GetConstant1() 6305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : graph_->GetConstantMinus1(); 63063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 63073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = new(zone()) HAdd(context, Top(), delta); 6308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceRepresentation(expr->op(), info, instr, rep); 6309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->AssumeRepresentation(rep); 6310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(instr); 6311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 6312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCountOperation(CountOperation* expr) { 6316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 63198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Expression* target = expr->expression(); 6320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = target->AsVariableProxy(); 6321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = target->AsProperty(); 6322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy == NULL && prop == NULL) { 6323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("invalid lhs in count operation"); 6324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Match the full code generator stack by simulating an extra stack 6327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // element for postfix operations in a non-effect context. The return 6328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // value is ToNumber(input). 6329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool returns_original_input = 6330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch expr->is_postfix() && !ast_context()->IsEffect(); 6331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* input = NULL; // ToNumber(original_input). 6332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* after = NULL; // The result after incrementing or decrementing. 6333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy != NULL) { 6335589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 63363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->mode() == CONST) { 63373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return Bailout("unsupported count operation with const"); 63383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument of the count operation is a variable, not a property. 6340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(prop == NULL); 6341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(target)); 6342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch after = BuildIncrement(returns_original_input, expr); 6344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch input = returns_original_input ? Top() : Pop(); 6345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(after); 6346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6347589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 6348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: 6349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HandleGlobalVariableAssignment(var, 6350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch after, 6351589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch expr->position(), 6352589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch expr->AssignmentId()); 6353589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 6354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 6355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 6356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 6357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Bind(var, after); 6358589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 6359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 6360589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: { 6361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Bail out if we try to mutate a parameter value in a function 6362589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // using the arguments object. We do not (yet) correctly handle the 6363589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // arguments property of the function. 6364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (info()->scope()->arguments() != NULL) { 6365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Parameters will rewrite to context slots. We have no direct 6366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // way to detect that the variable is a parameter so we use a 6367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // linear search of the parameter list. 6368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int count = info()->scope()->num_parameters(); 6369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch for (int i = 0; i < count; ++i) { 6370589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var == info()->scope()->parameter(i)) { 6371589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Bailout("assignment to parameter in arguments object"); 6372589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 63733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 63743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6375589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 6376589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = BuildContextChainWalk(var); 63773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HStoreContextSlot::Mode mode = 63783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (var->mode() == LET || var->mode() == CONST_HARMONY) 63793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; 6380589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HStoreContextSlot* instr = 63813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HStoreContextSlot(context, var->index(), mode, after); 6382589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddInstruction(instr); 63833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (instr->HasObservableSideEffects()) { 63843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddSimulate(expr->AssignmentId()); 63853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 6386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 63873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 63883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6389589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: 6390589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Bailout("lookup variable in count operation"); 6391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument of the count operation is a property. 6395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(prop != NULL); 6396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prop->RecordTypeFeedback(oracle()); 6397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->key()->IsPropertyName()) { 6399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named property. 6400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (returns_original_input) Push(graph_->GetConstantUndefined()); 6401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 6403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Top(); 6404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* load = NULL; 6406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->IsMonomorphic()) { 6407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 6408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = prop->GetReceiverTypes()->first(); 6409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamed(obj, prop, map, name); 6410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamedGeneric(obj, prop); 6412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 64143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (load->HasObservableSideEffects()) AddSimulate(expr->CountId()); 6415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch after = BuildIncrement(returns_original_input, expr); 6417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch input = Pop(); 6418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* store = BuildStoreNamed(obj, after, prop); 6420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 6421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Overwrite the receiver in the bailout environment with the result 6423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the operation, and the placeholder with the original value if 6424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // necessary. 6425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(0, after); 6426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (returns_original_input) environment()->SetExpressionStackAt(1, input); 64273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); 6428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed property. 6431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (returns_original_input) Push(graph_->GetConstantUndefined()); 6432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 6434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 6435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = environment()->ExpressionStackAt(1); 6436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = environment()->ExpressionStackAt(0); 6437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 64383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool has_side_effects = false; 64393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* load = HandleKeyedElementAccess( 64403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch obj, key, NULL, prop, expr->CountId(), RelocInfo::kNoPosition, 64413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch false, // is_store 64423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &has_side_effects); 64433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Push(load); 64443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (has_side_effects) AddSimulate(expr->CountId()); 6445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch after = BuildIncrement(returns_original_input, expr); 6447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch input = Pop(); 6448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 64498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->RecordTypeFeedback(oracle()); 64503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), 64513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RelocInfo::kNoPosition, 64523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch true, // is_store 64533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &has_side_effects); 6454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop the key from the bailout environment. Overwrite the receiver 6456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // with the result of the operation, and the placeholder with the 6457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // original value if necessary. 6458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(1); 6459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(0, after); 6460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (returns_original_input) environment()->SetExpressionStackAt(1, input); 64613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(has_side_effects); // Stores always have side effects. 64623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddSimulate(expr->AssignmentId()); 6463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Drop(returns_original_input ? 2 : 1); 64673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(expr->is_postfix() ? input : after); 6468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 64713fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, 64723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* string, 64731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* index) { 64748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(string)); 6475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(HCheckInstanceType::NewIsString(string)); 64768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStringLength* length = new(zone()) HStringLength(string); 64771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(length); 64787d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch HInstruction* checked_index = 64797d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch AddInstruction(new(zone()) HBoundsCheck(index, length)); 64803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return new(zone()) HStringCharCodeAt(context, string, checked_index); 64811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 64821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 64831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 6485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left, 6486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right) { 64873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 6488053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block TypeInfo info = oracle()->BinaryType(expr); 64893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (info.IsUninitialized()) { 64903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HSoftDeoptimize); 64913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->MarkAsDeoptimizing(); 64923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch info = TypeInfo::Unknown(); 64933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 64943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = NULL; 64953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (expr->op()) { 64963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::ADD: 64973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (info.IsString()) { 64983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(left)); 64993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(HCheckInstanceType::NewIsString(left)); 65003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(right)); 65013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(HCheckInstanceType::NewIsString(right)); 65023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr = new(zone()) HStringAdd(context, left, right); 65033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 65043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = HAdd::NewHAdd(zone(), context, left, right); 65053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 65063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::SUB: 65083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = HSub::NewHSub(zone(), context, left, right); 65093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::MUL: 65113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = HMul::NewHMul(zone(), context, left, right); 65123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::MOD: 65143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = HMod::NewHMod(zone(), context, left, right); 65153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::DIV: 65173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = HDiv::NewHDiv(zone(), context, left, right); 65183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::BIT_XOR: 65203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::BIT_AND: 65213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::BIT_OR: 65223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); 65233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::SAR: 65253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = HSar::NewHSar(zone(), context, left, right); 65263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::SHR: 65283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = HShr::NewHShr(zone(), context, left, right); 65293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::SHL: 65313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr = HShl::NewHShl(zone(), context, left, right); 65323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch default: 65343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch UNREACHABLE(); 65353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 65363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If we hit an uninitialized binary op stub we will get type info 6538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // for a smi operation. If one of the operands is a constant string 6539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // do not generate code assuming it is a smi operation. 6540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsSmi() && 6541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || 6542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { 6543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 6544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 65451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Representation rep = ToRepresentation(info); 65461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We only generate either int32 or generic tagged bitwise operations. 65471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) { 65481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block rep = Representation::Integer32(); 65491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceRepresentation(expr->op(), info, instr, rep); 6551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->AssumeRepresentation(rep); 6552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 6553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check for the form (%_ClassOf(foo) === 'BarClass'). 6557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsClassOfTest(CompareOperation* expr) { 6558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->op() != Token::EQ_STRICT) return false; 6559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CallRuntime* call = expr->left()->AsCallRuntime(); 6560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (call == NULL) return false; 6561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* literal = expr->right()->AsLiteral(); 6562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (literal == NULL) return false; 6563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!literal->handle()->IsString()) return false; 6564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 6565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(call->arguments()->length() == 1); 6566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 6567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 6571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 6574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (expr->op()) { 65753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::COMMA: 65763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return VisitComma(expr); 65773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::OR: 65783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::AND: 65793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return VisitLogicalExpression(expr); 65803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch default: 65813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return VisitArithmeticExpression(expr); 6582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitComma(BinaryOperation* expr) { 6587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForEffect(expr->left())); 6588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Visit the right subexpression in the same AST context as the entire 6589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // expression. 6590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Visit(expr->right()); 6591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 6593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 65943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { 65953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_logical_and = expr->op() == Token::AND; 6596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (ast_context()->IsTest()) { 6597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TestContext* context = TestContext::cast(ast_context()); 6598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Translate left subexpression. 6599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* eval_right = graph()->CreateBasicBlock(); 6600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_logical_and) { 6601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), 6602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch eval_right, 6603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context->if_false())); 6604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), 6606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context->if_true(), 6607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch eval_right)); 6608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Translate right subexpression by visiting it in the same AST 6611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // context as the entire expression. 6612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (eval_right->HasPredecessor()) { 6613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch eval_right->SetJoinId(expr->RightId()); 6614e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(eval_right); 6615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Visit(expr->right()); 6616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 6618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (ast_context()->IsValue()) { 6619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->left())); 6620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We need an extra block to maintain edge-split form. 6623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* empty_block = graph()->CreateBasicBlock(); 6624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* eval_right = graph()->CreateBasicBlock(); 662569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch unsigned test_id = expr->left()->test_id(); 662669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id)); 66273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBranch* test = is_logical_and 662869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ? new(zone()) HBranch(Top(), eval_right, empty_block, expected) 662969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch : new(zone()) HBranch(Top(), empty_block, eval_right, expected); 6630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current_block()->Finish(test); 6631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(eval_right); 6633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Drop(1); // Value of the left subexpression. 6634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForValue(expr->right())); 6635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* join_block = 6637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CreateJoin(empty_block, current_block(), expr->id()); 6638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(join_block); 66393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(Pop()); 6640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 6641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(ast_context()->IsEffect()); 6643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // In an effect context, we don't need the value of the left subexpression, 6644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // only its control flow and side effects. We need an extra block to 6645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // maintain edge-split form. 6646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* empty_block = graph()->CreateBasicBlock(); 6647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* right_block = graph()->CreateBasicBlock(); 6648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_logical_and) { 6649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block)); 6650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 6651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block)); 6652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TODO(kmillikin): Find a way to fix this. It's ugly that there are 6655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // actually two empty blocks (one here and one inserted by 6656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TestContext::BuildBranch, and that they both have an HSimulate though the 6657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // second one is not a merge node, and that we really have no good AST ID to 6658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // put on that first HSimulate. 6659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (empty_block->HasPredecessor()) { 6661053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block empty_block->SetJoinId(expr->id()); 6662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch empty_block = NULL; 6664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (right_block->HasPredecessor()) { 6667053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block right_block->SetJoinId(expr->RightId()); 6668053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block set_current_block(right_block); 6669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForEffect(expr->right())); 6670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch right_block = current_block(); 6671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch right_block = NULL; 6673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* join_block = 6676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CreateJoin(empty_block, right_block, expr->id()); 6677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(join_block); 6678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We did not materialize any value in the predecessor environments, 6679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // so there is no need to handle it here. 6680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 66843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { 6685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->left())); 6686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->right())); 6687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* right = Pop(); 6688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* left = Pop(); 6689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HInstruction* instr = BuildBinaryOperation(expr, left, right); 6690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->set_position(expr->position()); 66913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::TraceRepresentation(Token::Value op, 6696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TypeInfo info, 6697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value, 6698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation rep) { 6699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!FLAG_trace_representation) return; 6700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TODO(svenpanne) Under which circumstances are we actually not flexible? 6701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // At first glance, this looks a bit weird... 6702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool flexible = value->CheckFlag(HValue::kFlexibleRepresentation); 6703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Operation %s has type info %s, %schange representation assumption " 6704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "for %s (ID %d) from %s to %s\n", 6705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Token::Name(op), 6706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch info.ToString(), 6707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch flexible ? "" : " DO NOT ", 6708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value->Mnemonic(), 6709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch graph_->GetMaximumValueID(), 6710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value->representation().Mnemonic(), 6711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rep.Mnemonic()); 6712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HGraphBuilder::ToRepresentation(TypeInfo info) { 6716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsSmi()) return Representation::Integer32(); 6717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsInteger32()) return Representation::Integer32(); 6718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsDouble()) return Representation::Double(); 6719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsNumber()) return Representation::Double(); 6720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::Tagged(); 6721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 67243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, 67253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HTypeof* typeof_expr, 67263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<String> check) { 67273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note: The HTypeof itself is removed during canonicalization, if possible. 67283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* value = typeof_expr->value(); 67293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); 67303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->set_position(expr->position()); 67313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnControl(instr, expr->id()); 6732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 6733592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 6734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 67353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool MatchLiteralCompareNil(HValue* left, 67363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::Value op, 67373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* right, 67383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> nil, 67393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue** expr) { 67403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (left->IsConstant() && 67413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HConstant::cast(left)->handle().is_identical_to(nil) && 67423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::IsEqualityOp(op)) { 67433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *expr = right; 67443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 67453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 67463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 67473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 67483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 67493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 67503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool MatchLiteralCompareTypeof(HValue* left, 67513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::Value op, 67523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* right, 67533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HTypeof** typeof_expr, 67543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String>* check) { 67553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (left->IsTypeof() && 67563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::IsEqualityOp(op) && 67573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch right->IsConstant() && 67583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HConstant::cast(right)->HasStringValue()) { 67593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *typeof_expr = HTypeof::cast(left); 67603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch *check = Handle<String>::cast(HConstant::cast(right)->handle()); 67613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return true; 67623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 67633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return false; 67643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 67653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 67663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 67673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsLiteralCompareTypeof(HValue* left, 67683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::Value op, 67693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* right, 67703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HTypeof** typeof_expr, 67713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String>* check) { 67723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) || 67733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MatchLiteralCompareTypeof(right, op, left, typeof_expr, check); 67743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 67753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 67763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 67773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsLiteralCompareNil(HValue* left, 67783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::Value op, 67793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* right, 67803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> nil, 67813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue** expr) { 67823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return MatchLiteralCompareNil(left, op, right, nil, expr) || 67833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MatchLiteralCompareNil(right, op, left, nil, expr); 67843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 67853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 67863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 67873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic bool IsLiteralCompareBool(HValue* left, 67883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Token::Value op, 67893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* right) { 67903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return op == Token::EQ_STRICT && 67913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || 67923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); 6793c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch} 6794c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 6795c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 6796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 6797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 6800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (IsClassOfTest(expr)) { 6801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CallRuntime* call = expr->left()->AsCallRuntime(); 68023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(call->arguments()->length() == 1); 6803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 6804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 6805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* literal = expr->right()->AsLiteral(); 6806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> rhs = Handle<String>::cast(literal->handle()); 68073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HClassOfTestAndBranch* instr = 68083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HClassOfTestAndBranch(value, rhs); 6809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 68103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(instr, expr->id()); 68113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 68123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 68133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch TypeInfo type_info = oracle()->CompareType(expr); 68143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if this expression was ever executed according to type feedback. 68153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Note that for the special typeof/null/undefined cases we get unknown here. 68163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (type_info.IsUninitialized()) { 68173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HSoftDeoptimize); 68183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->MarkAsDeoptimizing(); 68193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch type_info = TypeInfo::Unknown(); 68203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 68213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->left())); 6823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->right())); 6824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 68253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 6826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 6827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 6828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Value op = expr->op(); 6829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 68303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HTypeof* typeof_expr = NULL; 68313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> check; 68323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) { 68333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return HandleLiteralCompareTypeof(expr, typeof_expr, check); 68343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 68353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* sub_expr = NULL; 68363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Factory* f = graph()->isolate()->factory(); 68373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) { 68383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); 68393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 68403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) { 68413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return HandleLiteralCompareNil(expr, sub_expr, kNullValue); 68423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 68433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (IsLiteralCompareBool(left, op, right)) { 68443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HCompareObjectEqAndBranch* result = 68453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCompareObjectEqAndBranch(left, right); 68463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result->set_position(expr->position()); 68473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnControl(result, expr->id()); 68483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 68493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::INSTANCEOF) { 6851086aeeaae12517475c22695a200be45495516549Ben Murdoch // Check to see if the rhs of the instanceof is a global function not 6852086aeeaae12517475c22695a200be45495516549Ben Murdoch // residing in new space. If it is we assume that the function will stay the 6853086aeeaae12517475c22695a200be45495516549Ben Murdoch // same. 6854086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<JSFunction> target = Handle<JSFunction>::null(); 6855589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->right()->AsVariableProxy(); 6856589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); 6857086aeeaae12517475c22695a200be45495516549Ben Murdoch if (global_function && 6858e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch info()->has_global_object() && 6859e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !info()->global_object()->IsAccessCheckNeeded()) { 6860589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Handle<String> name = proxy->name(); 6861e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<GlobalObject> global(info()->global_object()); 68623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 6863086aeeaae12517475c22695a200be45495516549Ben Murdoch global->Lookup(*name, &lookup); 68643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup.IsFound() && 6865086aeeaae12517475c22695a200be45495516549Ben Murdoch lookup.type() == NORMAL && 6866086aeeaae12517475c22695a200be45495516549Ben Murdoch lookup.GetValue()->IsJSFunction()) { 6867086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); 6868086aeeaae12517475c22695a200be45495516549Ben Murdoch // If the function is in new space we assume it's more likely to 6869086aeeaae12517475c22695a200be45495516549Ben Murdoch // change and thus prefer the general IC code. 687044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!isolate()->heap()->InNewSpace(*candidate)) { 6871086aeeaae12517475c22695a200be45495516549Ben Murdoch target = candidate; 6872086aeeaae12517475c22695a200be45495516549Ben Murdoch } 6873086aeeaae12517475c22695a200be45495516549Ben Murdoch } 6874086aeeaae12517475c22695a200be45495516549Ben Murdoch } 6875086aeeaae12517475c22695a200be45495516549Ben Murdoch 6876086aeeaae12517475c22695a200be45495516549Ben Murdoch // If the target is not null we have found a known global function that is 6877086aeeaae12517475c22695a200be45495516549Ben Murdoch // assumed to stay the same for this instanceof. 6878086aeeaae12517475c22695a200be45495516549Ben Murdoch if (target.is_null()) { 68793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); 68803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 68813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, expr->id()); 6882086aeeaae12517475c22695a200be45495516549Ben Murdoch } else { 68838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckFunction(right, target)); 68843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstanceOfKnownGlobal* result = 68853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HInstanceOfKnownGlobal(context, left, target); 68863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 68873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, expr->id()); 6888086aeeaae12517475c22695a200be45495516549Ben Murdoch } 6889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::IN) { 68903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HIn* result = new(zone()) HIn(context, left, right); 68913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 68923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, expr->id()); 6893e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (type_info.IsNonPrimitive()) { 6894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (op) { 6895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ: 6896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ_STRICT: { 68973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Can we get away with map check and not instance type check? 68983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> map = oracle()->GetCompareMap(expr); 68993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!map.is_null()) { 69003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckNonSmi(left)); 69013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckMap(left, map, NULL, 69023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS)); 69033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckNonSmi(right)); 69043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckMap(right, map, NULL, 69053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS)); 69063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HCompareObjectEqAndBranch* result = 69073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCompareObjectEqAndBranch(left, right); 69083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result->set_position(expr->position()); 69093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnControl(result, expr->id()); 69103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 69113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckNonSmi(left)); 69123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(HCheckInstanceType::NewIsSpecObject(left)); 69133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new(zone()) HCheckNonSmi(right)); 69143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(HCheckInstanceType::NewIsSpecObject(right)); 69153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HCompareObjectEqAndBranch* result = 69163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCompareObjectEqAndBranch(left, right); 69173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result->set_position(expr->position()); 69183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnControl(result, expr->id()); 69193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 6920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 6922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("Unsupported non-primitive compare"); 6923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) && 6925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (op == Token::EQ || op == Token::EQ_STRICT)) { 69263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(left)); 69273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(HCheckInstanceType::NewIsSymbol(left)); 69283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(right)); 69293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(HCheckInstanceType::NewIsSymbol(right)); 69303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HCompareObjectEqAndBranch* result = 69313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HCompareObjectEqAndBranch(left, right); 69323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 69333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, expr->id()); 6934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6935e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Representation r = ToRepresentation(type_info); 69363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (r.IsTagged()) { 69373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HCompareGeneric* result = 69383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HCompareGeneric(context, left, right, op); 69393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 69403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, expr->id()); 69413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 69423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HCompareIDAndBranch* result = 69433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HCompareIDAndBranch(left, right, op); 69443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 69453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->SetInputRepresentation(r); 69463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, expr->id()); 69473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 69523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 69533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* value, 69543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NilValue nil) { 6955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 69583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EqualityKind kind = 69593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; 69603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); 69613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch instr->set_position(expr->position()); 69623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(instr, expr->id()); 6963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThisFunction(ThisFunction* expr) { 6967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 69703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HThisFunction* self = new(zone()) HThisFunction( 69713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function_state()->compilation_info()->closure()); 69723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(self, expr->id()); 6973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 69763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) { 69773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int length = declarations->length(); 69783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int global_count = 0; 69793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < declarations->length(); i++) { 69803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Declaration* decl = declarations->at(i); 69813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration(); 69823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HandleDeclaration(decl->proxy(), 69833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch decl->mode(), 69843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch fun_decl != NULL ? fun_decl->fun() : NULL, 69853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &global_count); 69863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 69873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 69883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Batch declare global functions and variables. 69893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (global_count > 0) { 69903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<FixedArray> array = 69913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch isolate()->factory()->NewFixedArray(2 * global_count, TENURED); 69923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int j = 0, i = 0; i < length; i++) { 69933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Declaration* decl = declarations->at(i); 69943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Variable* var = decl->proxy()->var(); 69953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 69963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->IsUnallocated()) { 69973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch array->set(j++, *(var->name())); 69983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration(); 69993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (fun_decl == NULL) { 70003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (var->binding_needs_init()) { 70013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // In case this binding needs initialization use the hole. 70023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch array->set_the_hole(j++); 70033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 70043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch array->set_undefined(j++); 70053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 70063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 70073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> function = 70083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Compiler::BuildFunctionInfo(fun_decl->fun(), info()->script()); 70093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for stack-overflow exception. 70103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function.is_null()) { 70113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch SetStackOverflow(); 70123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 70133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 70143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch array->set(j++, *function); 70153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 70163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 70173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 70183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | 70193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeclareGlobalsNativeFlag::encode(info()->is_native()) | 70203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DeclareGlobalsLanguageMode::encode(info()->language_mode()); 70213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* result = 70223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HDeclareGlobals(environment()->LookupContext(), 70233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch array, 70243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flags); 70253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(result); 70263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 7027589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 7028589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 7029589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 7030589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid HGraphBuilder::HandleDeclaration(VariableProxy* proxy, 70313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch VariableMode mode, 70323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FunctionLiteral* function, 70333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int* global_count) { 7034589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 70353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool binding_needs_init = 70363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (mode == CONST || mode == CONST_HARMONY || mode == LET); 7037589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 7038589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: 70393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++(*global_count); 70403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return; 7041589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 7042589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 7043589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: 70443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (binding_needs_init || function != NULL) { 7045589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* value = NULL; 70463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function != NULL) { 70473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForValue(function)); 704885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch value = Pop(); 70493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 70503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value = graph()->GetConstantHole(); 7051589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 7052589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 7053589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = environment()->LookupContext(); 70543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HStoreContextSlot* store = new HStoreContextSlot( 70553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch context, var->index(), HStoreContextSlot::kNoCheck, value); 7056589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddInstruction(store); 70573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (store->HasObservableSideEffects()) AddSimulate(proxy->id()); 7058589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 7059589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch environment()->Bind(var, value); 7060589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 7061589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 7062589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 7063589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: 7064589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Bailout("unsupported lookup slot in declaration"); 70653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 70693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) { 70703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 70713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 70723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { 70753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 70763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 70773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) { 70803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 70813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 70823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) { 70853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 70863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 70873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) { 70903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch UNREACHABLE(); 70913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 70923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) { 70953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(rossberg) 70963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 70973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 70993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitModuleVariable(ModuleVariable* module) { 71003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(rossberg) 71013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 71023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 71033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 71043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitModulePath(ModulePath* module) { 71053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(rossberg) 71063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 71073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 71083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 71093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::VisitModuleUrl(ModuleUrl* module) { 71103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // TODO(rossberg) 71113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 71123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 71133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Generators for inline runtime functions. 7115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for types. 7116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSmi(CallRuntime* call) { 7117e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); 71213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7125e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { 7126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HHasInstanceTypeAndBranch* result = 71303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HHasInstanceTypeAndBranch(value, 71313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FIRST_SPEC_OBJECT_TYPE, 71323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LAST_SPEC_OBJECT_TYPE); 71333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsFunction(CallRuntime* call) { 7138e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HHasInstanceTypeAndBranch* result = 71423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); 71433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { 7148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HHasCachedArrayIndexAndBranch* result = 71523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HHasCachedArrayIndexAndBranch(value); 71533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsArray(CallRuntime* call) { 7158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HHasInstanceTypeAndBranch* result = 71623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); 71633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { 7168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HHasInstanceTypeAndBranch* result = 71723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); 71733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsObject(CallRuntime* call) { 7178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); 71823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { 7187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: IsNonNegativeSmi"); 7188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { 7192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(call->arguments()->length() == 1); 7193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = Pop(); 71953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HIsUndetectableAndBranch* result = 71963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HIsUndetectableAndBranch(value); 71973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 7202e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime* call) { 7203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout( 7204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 7205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 72081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Support for construct call checks. 7209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 7210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 0); 72118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (function_state()->outer() != NULL) { 72123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We are generating graph for inlined function. 72133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* value = function_state()->is_construct() 72143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? graph()->GetConstantTrue() 72153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : graph()->GetConstantFalse(); 72163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnValue(value); 72178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 72183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, 72193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch call->id()); 72208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 7221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for arguments.length and arguments[?]. 7225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 722642effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // Our implementation of arguments (based on this stack frame or an 722742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // adapter below it) does not work for inlined functions. This runtime 722842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // function is blacklisted by AstNode::IsInlineable. 722942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch ASSERT(function_state()->outer() == NULL); 7230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 0); 72318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 72328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HArgumentsLength* result = new(zone()) HArgumentsLength(elements); 72333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7237e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArguments(CallRuntime* call) { 723842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // Our implementation of arguments (based on this stack frame or an 723942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // adapter below it) does not work for inlined functions. This runtime 724042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // function is blacklisted by AstNode::IsInlineable. 724142effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch ASSERT(function_state()->outer() == NULL); 7242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* index = Pop(); 72458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 72468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); 72478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HAccessArgumentsAt* result = 72488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HAccessArgumentsAt(elements, length, index); 72493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for accessing the class and value fields of an object. 7254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateClassOf(CallRuntime* call) { 7255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The special form detected by IsClassOfTest is detected before we get here 7256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // and does not cause a bailout. 7257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: ClassOf"); 7258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateValueOf(CallRuntime* call) { 7262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 72658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValueOf* result = new(zone()) HValueOf(value); 72663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 72703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::GenerateDateField(CallRuntime* call) { 72713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(call->arguments()->length() == 2); 72723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); 72733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); 72743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 72753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* date = Pop(); 72763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HDateField* result = new(zone()) HDateField(date, index); 72773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnInstruction(result, call->id()); 72783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 72793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 72803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { 72823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(call->arguments()->length() == 2); 72833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 72843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 72853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* value = Pop(); 72863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* object = Pop(); 72873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is a not a smi. 72883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object); 72893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* if_smi = graph()->CreateBasicBlock(); 72903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); 72913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* join = graph()->CreateBasicBlock(); 72923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch smicheck->SetSuccessorAt(0, if_smi); 72933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch smicheck->SetSuccessorAt(1, if_heap_object); 72943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Finish(smicheck); 72953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if_smi->Goto(join); 72963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 72973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if object is a JSValue. 72983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(if_heap_object); 72993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HHasInstanceTypeAndBranch* typecheck = 73003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); 73013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* if_js_value = graph()->CreateBasicBlock(); 73023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* not_js_value = graph()->CreateBasicBlock(); 73033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch typecheck->SetSuccessorAt(0, if_js_value); 73043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch typecheck->SetSuccessorAt(1, not_js_value); 73053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Finish(typecheck); 73063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch not_js_value->Goto(join); 73073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 73083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Create in-object property store to kValueOffset. 73093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(if_js_value); 73103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name = isolate()->factory()->undefined_symbol(); 73113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(new HStoreNamedField(object, 73123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 73133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch value, 73143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch true, // in-object store. 73153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSValue::kValueOffset)); 73163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if_js_value->Goto(join); 73173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch join->SetJoinId(call->id()); 73183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(join); 73193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnValue(value); 7320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for charCodeAt(n). 7324e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { 7325e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 2); 7326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 73281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* index = Pop(); 73291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* string = Pop(); 73303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 73313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index); 73323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n]. 7337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { 733844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(call->arguments()->length() == 1); 7339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 734044f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* char_code = Pop(); 73413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 73423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharFromCode* result = 73433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HStringCharFromCode(context, char_code); 73443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n]. 7349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { 735044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(call->arguments()->length() == 2); 7351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 735344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* index = Pop(); 735444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* string = Pop(); 73553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 73563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); 735744f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(char_code); 73583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharFromCode* result = 73593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HStringCharFromCode(context, char_code); 73603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for object equality testing. 7365e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { 7366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 2); 7367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 7369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 7370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 73713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HCompareObjectEqAndBranch* result = 73723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HCompareObjectEqAndBranch(left, right); 73733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7377e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateLog(CallRuntime* call) { 7378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // %_Log is ignored in optimized code. 73793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 7380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for Math.random(). 7384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { 73853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* context = environment()->LookupContext(); 73863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 73873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AddInstruction(global_object); 73883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HRandom* result = new(zone()) HRandom(global_object); 73893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringAdd. 7394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringAdd(CallRuntime* call) { 7395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(2, call->arguments()->length()); 7396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 73988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); 7399e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(2); 74003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for SubString. 7405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSubString(CallRuntime* call) { 7406e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(3, call->arguments()->length()); 7407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 74098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); 7410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(3); 74113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringCompare. 7416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCompare(CallRuntime* call) { 7417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(2, call->arguments()->length()); 7418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 74208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 74218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::StringCompare, 2); 7422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(2); 74233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for direct calls from JavaScript to native RegExp code. 7428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { 7429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(4, call->arguments()->length()); 7430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 74328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); 7433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(4); 74343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Construct a RegExp exec result with two in-object properties. 7439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { 7440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(3, call->arguments()->length()); 7441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 7443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = 74448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); 7445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(3); 74463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for fast native caches. 7451e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { 7452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: GetFromCache"); 7453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for number to string. 7457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateNumberToString(CallRuntime* call) { 7458e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 7459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 74618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 74628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::NumberToString, 1); 7463e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 74643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call for custom callbacks. 7469e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateCallFunction(CallRuntime* call) { 7470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 1 ~ The function to call is not itself an argument to the call. 7471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int arg_count = call->arguments()->length() - 1; 7472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(arg_count >= 1); // There's always at least a receiver. 7473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < arg_count; ++i) { 7475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); 7476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->last())); 74783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* function = Pop(); 7480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 74813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Branch for function proxies, or other non-functions. 74833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HHasInstanceTypeAndBranch* typecheck = 74843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); 74853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); 74863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); 74873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HBasicBlock* join = graph()->CreateBasicBlock(); 74883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch typecheck->SetSuccessorAt(0, if_jsfunction); 74893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch typecheck->SetSuccessorAt(1, if_nonfunction); 74903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current_block()->Finish(typecheck); 74913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(if_jsfunction); 74933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* invoke_result = AddInstruction( 74943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HInvokeFunction(context, function, arg_count)); 7495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Drop(arg_count); 74963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(invoke_result); 74973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if_jsfunction->Goto(join); 74983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 74993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(if_nonfunction); 75003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HInstruction* call_result = AddInstruction( 75013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCallFunction(context, function, arg_count)); 75023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Drop(arg_count); 75033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Push(call_result); 75043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if_nonfunction->Goto(join); 75053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch set_current_block(join); 75073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch join->SetJoinId(call->id()); 75083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnValue(Pop()); 7509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call to math functions. 7513e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathPow(CallRuntime* call) { 7514e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(2, call->arguments()->length()); 7515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 7517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 7518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 75198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HPower* result = new(zone()) HPower(left, right); 75203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSin(CallRuntime* call) { 7525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 7526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 75288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 75298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 7530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::SIN); 7531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 75323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathCos(CallRuntime* call) { 7537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 7538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 75408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 75418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 7542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::COS); 7543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 75443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 75483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid HGraphBuilder::GenerateMathTan(CallRuntime* call) { 75493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 75503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 75513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* context = environment()->LookupContext(); 75523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HCallStub* result = 75533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 75543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result->set_transcendental_type(TranscendentalCache::TAN); 75553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Drop(1); 75563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return ast_context()->ReturnInstruction(result, call->id()); 75573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 75583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 75593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathLog(CallRuntime* call) { 7561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 7562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 75648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 75658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 7566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::LOG); 7567e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 75683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { 7573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: MathSqrt"); 7574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check whether two RegExps are equivalent 7578e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { 7579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: IsRegExpEquivalent"); 7580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7583e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { 7584e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HValue* value = Pop(); 75878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); 75883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7592e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { 7593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: FastAsciiArrayJoin"); 7594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef CHECK_BAILOUT 7598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#undef CHECK_ALIVE 7599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(HEnvironment* outer, 7602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Scope* scope, 7603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> closure) 7604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : closure_(closure), 7605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_(0), 7606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch assigned_variables_(4), 76073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_type_(JS_FUNCTION), 7608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_(0), 7609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch specials_count_(1), 7610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_(0), 7611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_(outer), 7612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pop_count_(0), 7613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch push_count_(0), 76145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ast_id_(AstNode::kNoNumber) { 7615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); 7616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(const HEnvironment* other) 7620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : values_(0), 7621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch assigned_variables_(0), 76223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_type_(JS_FUNCTION), 7623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_(0), 7624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch specials_count_(1), 7625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_(0), 7626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_(NULL), 7627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pop_count_(0), 7628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch push_count_(0), 76295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ast_id_(other->ast_id()) { 7630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Initialize(other); 7631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 76343ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHEnvironment::HEnvironment(HEnvironment* outer, 76353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> closure, 76363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameType frame_type, 76373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int arguments) 76383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : closure_(closure), 76393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch values_(arguments), 76403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch assigned_variables_(0), 76413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_type_(frame_type), 76423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch parameter_count_(arguments), 76433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch local_count_(0), 76443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch outer_(outer), 76453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch pop_count_(0), 76463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch push_count_(0), 76473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ast_id_(AstNode::kNoNumber) { 76483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 76493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 76503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::Initialize(int parameter_count, 7652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int local_count, 7653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int stack_height) { 7654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_ = parameter_count; 7655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_ = local_count; 7656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Avoid reallocating the temporaries' backing store on the first Push. 7658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int total = parameter_count + specials_count_ + local_count + stack_height; 7659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_.Initialize(total + 4); 7660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < total; ++i) values_.Add(NULL); 7661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 76649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Initialize(const HEnvironment* other) { 76659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block closure_ = other->closure(); 76669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_.AddAll(other->values_); 76679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block assigned_variables_.AddAll(other->assigned_variables_); 76683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_type_ = other->frame_type_; 76699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block parameter_count_ = other->parameter_count_; 76709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block local_count_ = other->local_count_; 76719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy. 76729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block pop_count_ = other->pop_count_; 76739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block push_count_ = other->push_count_; 76749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ast_id_ = other->ast_id_; 76759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 76769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 76779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) { 7679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!block->IsLoopHeader()); 7680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(values_.length() == other->values_.length()); 7681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = values_.length(); 7683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; ++i) { 7684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = values_[i]; 7685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != NULL && value->IsPhi() && value->block() == block) { 7686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is already a phi for the i'th value. 7687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = HPhi::cast(value); 7688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Assert index is correct and that we haven't missed an incoming edge. 7689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->merged_index() == i); 7690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->OperandCount() == block->predecessors()->length()); 7691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(other->values_[i]); 7692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (values_[i] != other->values_[i]) { 7693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is a fresh value on the incoming edge, a phi is needed. 7694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(values_[i] != NULL && other->values_[i] != NULL); 76958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HPhi* phi = new(block->zone()) HPhi(i); 7696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* old_value = values_[i]; 7697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < block->predecessors()->length(); j++) { 7698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(old_value); 7699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(other->values_[i]); 7701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch this->values_[i] = phi; 7702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->AddPhi(phi); 7703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 77089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Bind(int index, HValue* value) { 77099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(value != NULL); 77109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!assigned_variables_.Contains(index)) { 77119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block assigned_variables_.Add(index); 77129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 77139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_[index] = value; 7714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 77179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::HasExpressionAt(int index) const { 7718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return index >= parameter_count_ + specials_count_ + local_count_; 77199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 77209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::ExpressionStackIsEmpty() const { 77233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(length() >= first_expression_index()); 77243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return length() == first_expression_index(); 77259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 77269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) { 77299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int count = index_from_top + 1; 77309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index = values_.length() - count; 77319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(HasExpressionAt(index)); 77329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // The push count must include at least the element in question or else 77339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // the new value will not be included in this environment's history. 77349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (push_count_ < count) { 77359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // This is the same effect as popping then re-pushing 'count' elements. 77369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block pop_count_ += (count - push_count_); 77379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block push_count_ = count; 77389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 77399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_[index] = value; 77409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 77419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Drop(int count) { 77449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = 0; i < count; ++i) { 77459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Pop(); 7746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::Copy() const { 77518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(closure()->GetIsolate()->zone()) HEnvironment(this); 7752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyWithoutHistory() const { 7756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* result = Copy(); 7757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->ClearHistory(); 7758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 7759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const { 7763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* new_env = Copy(); 7764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < values_.length(); ++i) { 77658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HPhi* phi = new(loop_header->zone()) HPhi(i); 7766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(values_[i]); 7767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_env->values_[i] = phi; 7768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_header->AddPhi(phi); 7769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_env->ClearHistory(); 7771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new_env; 7772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 77753ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer, 77763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> target, 77773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameType frame_type, 77783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int arguments) const { 77793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HEnvironment* new_env = new(closure()->GetIsolate()->zone()) 77803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HEnvironment(outer, target, frame_type, arguments + 1); 77813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i <= arguments; ++i) { // Include receiver. 77823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new_env->Push(ExpressionStackAt(arguments - i)); 77833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 77843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch new_env->ClearHistory(); 77853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return new_env; 77863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 77873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 77883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHEnvironment* HEnvironment::CopyForInlining( 7790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<JSFunction> target, 77913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int arguments, 7792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FunctionLiteral* function, 7793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HConstant* undefined, 77943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind, 77953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_construct) const { 77963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(frame_type() == JS_FUNCTION); 77973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 77983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Zone* zone = closure()->GetIsolate()->zone(); 77993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Outer environment is a copy of this one without the arguments. 7801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity = function->scope()->num_parameters(); 78023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 7803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* outer = Copy(); 78043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch outer->Drop(arguments + 1); // Including receiver. 7805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer->ClearHistory(); 78063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 78073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_construct) { 78083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Create artificial constructor stub environment. The receiver should 78093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // actually be the constructor function, but we pass the newly allocated 78103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object instead, DoComputeConstructStubFrame() relies on that. 78113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments); 78123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 78133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 78143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (arity != arguments) { 78153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Create artificial arguments adaptation environment. 78163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments); 78173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 78183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 78198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HEnvironment* inner = 78208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone) HEnvironment(outer, function->scope(), target); 7821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the argument values from the original environment. 78223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i <= arity; ++i) { // Include receiver. 78233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch HValue* push = (i <= arguments) ? 78243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExpressionStackAt(arguments - i) : undefined; 78253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch inner->SetValueAt(i, push); 78263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 78273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If the function we are inlining is a strict mode function or a 78283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // builtin function, pass undefined as the receiver for function 78293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // calls (instead of the global receiver). 78303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if ((target->shared()->native() || !function->is_classic_mode()) && 78313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch call_kind == CALL_AS_FUNCTION && !is_construct) { 7832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inner->SetValueAt(0, undefined); 7833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 78343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch inner->SetValueAt(arity + 1, LookupContext()); 7835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = arity + 2; i < inner->length(); ++i) { 7836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inner->SetValueAt(i, undefined); 7837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 78398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch inner->set_ast_id(AstNode::kFunctionEntryId); 7840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return inner; 7841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintTo(StringStream* stream) { 78459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = 0; i < length(); i++) { 7846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (i == 0) stream->Add("parameters\n"); 7847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i == parameter_count()) stream->Add("specials\n"); 7848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i == parameter_count() + specials_count()) stream->Add("locals\n"); 7849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i == parameter_count() + specials_count() + local_count()) { 78503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stream->Add("expressions\n"); 7851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* val = values_.at(i); 7853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("%d: ", i); 7854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (val != NULL) { 7855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch val->PrintNameTo(stream); 7856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 7857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("NULL"); 7858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("\n"); 7860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 78613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintF("\n"); 7862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintToStd() { 7866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HeapStringAllocator string_allocator; 7867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StringStream trace(&string_allocator); 7868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintTo(&trace); 7869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("%s", *trace.ToCString()); 7870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceCompilation(FunctionLiteral* function) { 7874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "compilation"); 7875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = function->debug_name(); 7876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", *name->ToCString()); 7877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("method", *name->ToCString()); 7878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); 7879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLithium(const char* name, LChunk* chunk) { 7883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Trace(name, chunk->graph(), chunk); 7884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceHydrogen(const char* name, HGraph* graph) { 7888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Trace(name, graph, NULL); 7889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { 7893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "cfg"); 7894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", name); 7895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HBasicBlock*>* blocks = graph->blocks(); 7896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks->length(); i++) { 7897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* current = blocks->at(i); 7898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag block_tag(this, "block"); 7899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("name", current->block_id()); 7900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty("from_bci", -1); 7901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty("to_bci", -1); 7902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!current->predecessors()->is_empty()) { 7904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIndent(); 7905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("predecessors"); 7906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < current->predecessors()->length(); ++j) { 7907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id()); 7908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("\n"); 7910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 7911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("predecessors"); 7912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 79143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (current->end()->SuccessorCount() == 0) { 7915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("successors"); 79163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 79173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintIndent(); 79183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trace_.Add("successors"); 79193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) { 79203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trace_.Add(" \"B%d\"", it.Current()->block_id()); 79213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 79223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trace_.Add("\n"); 7923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("xhandlers"); 79263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const char* flags = current->IsLoopSuccessorDominator() 79273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? "dom-loop-succ" 79283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : ""; 79293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PrintStringProperty("flags", flags); 7930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->dominator() != NULL) { 7932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("dominator", current->dominator()->block_id()); 7933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7935589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrintIntProperty("loop_depth", current->LoopNestingDepth()); 7936589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 7937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk != NULL) { 7938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int first_index = current->first_instruction_index(); 7939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_index = current->last_instruction_index(); 7940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty( 7941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "first_lir_id", 7942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(first_index).Value()); 7943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty( 7944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "last_lir_id", 7945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(last_index).Value()); 7946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 7949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag states_tag(this, "states"); 7950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag locals_tag(this, "locals"); 7951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int total = current->phis()->length(); 7952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintIntProperty("size", current->phis()->length()); 7953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintStringProperty("method", "None"); 7954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < total; ++j) { 7955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = current->phis()->at(j); 7956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintIndent(); 7957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d ", phi->merged_index()); 7958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->PrintNameTo(&trace_); 7959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" "); 7960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->PrintTo(&trace_); 7961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("\n"); 7962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 7966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag HIR_tag(this, "HIR"); 7967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instruction = current->first(); 7968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instruction != NULL) { 7969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int bci = 0; 7970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int uses = instruction->UseCount(); 7971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintIndent(); 7972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d %d ", bci, uses); 7973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction->PrintNameTo(&trace_); 7974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" "); 7975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction->PrintTo(&trace_); 7976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" <|@\n"); 7977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction = instruction->next(); 7978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk != NULL) { 7983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag LIR_tag(this, "LIR"); 7984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int first_index = current->first_instruction_index(); 7985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_index = current->last_instruction_index(); 7986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first_index != -1 && last_index != -1) { 7987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<LInstruction*>* instructions = chunk->instructions(); 7988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = first_index; i <= last_index; ++i) { 7989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LInstruction* linstr = instructions->at(i); 7990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (linstr != NULL) { 7991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintIndent(); 7992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d ", 7993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(i).Value()); 7994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch linstr->PrintTo(&trace_); 7995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" <|@\n"); 7996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) { 8005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "intervals"); 8006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", name); 8007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 800844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges(); 8009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < fixed_d->length(); ++i) { 8010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(fixed_d->at(i), "fixed"); 8011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 801344f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges(); 8014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < fixed->length(); ++i) { 8015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(fixed->at(i), "fixed"); 8016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges(); 8019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < live_ranges->length(); ++i) { 8020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(live_ranges->at(i), "object"); 8021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRange(LiveRange* range, const char* type) { 8026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range != NULL && !range->IsEmpty()) { 8027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintIndent(); 8028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d %s", range->id(), type); 8029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range->HasRegisterAssigned()) { 80303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LOperand* op = range->CreateAssignedOperand(ZONE); 8031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int assigned_reg = op->index(); 8032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op->IsDoubleRegister()) { 8033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"%s\"", 8034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoubleRegister::AllocationIndexToString(assigned_reg)); 8035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsRegister()); 8037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg)); 8038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (range->IsSpilled()) { 8040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op = range->TopLevel()->GetSpillOperand(); 8041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op->IsDoubleStackSlot()) { 8042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"double_stack:%d\"", op->index()); 8043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsStackSlot()); 8045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"stack:%d\"", op->index()); 8046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int parent_index = -1; 8049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range->IsChild()) { 8050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parent_index = range->parent()->id(); 8051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parent_index = range->id(); 8053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op = range->FirstHint(); 8055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int hint_index = -1; 80563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (op != NULL && op->IsUnallocated()) { 80573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch hint_index = LUnallocated::cast(op)->virtual_register(); 80583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" %d %d", parent_index, hint_index); 8060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UseInterval* cur_interval = range->first_interval(); 8061e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (cur_interval != NULL && range->Covers(cur_interval->start())) { 8062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" [%d, %d[", 8063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval->start().Value(), 8064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval->end().Value()); 8065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval = cur_interval->next(); 8066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UsePosition* current_pos = range->first_pos(); 8069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current_pos != NULL) { 8070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) { 8071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" %d M", current_pos->pos().Value()); 8072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_pos = current_pos->next(); 8074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"\"\n"); 8077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::FlushToFile() { 8082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendChars(filename_, *trace_.ToCString(), trace_.length(), false); 8083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Reset(); 8084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 808744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HStatistics::Initialize(CompilationInfo* info) { 808844f0eee88ff00398ff7f715fab053374d808c90dSteve Block source_size_ += info->shared_info()->SourceSize(); 808944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 809044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 809144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStatistics::Print() { 8093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Timing results:\n"); 8094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int64_t sum = 0; 8095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < timing_.length(); ++i) { 8096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch sum += timing_[i]; 8097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < names_.length(); ++i) { 8100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("%30s", names_[i]); 8101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double ms = static_cast<double>(timing_[i]) / 1000; 8102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double percent = static_cast<double>(timing_[i]) * 100 / sum; 8103b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF(" - %7.3f ms / %4.1f %% ", ms, percent); 8104b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 8105b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch unsigned size = sizes_[i]; 8106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch double size_percent = static_cast<double>(size) * 100 / total_size_; 8107b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF(" %8u bytes / %4.1f %%\n", size, size_percent); 8108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 810944f0eee88ff00398ff7f715fab053374d808c90dSteve Block double source_size_in_kb = static_cast<double>(source_size_) / 1024; 811044f0eee88ff00398ff7f715fab053374d808c90dSteve Block double normalized_time = source_size_in_kb > 0 811144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? (static_cast<double>(sum) / 1000) / source_size_in_kb 811244f0eee88ff00398ff7f715fab053374d808c90dSteve Block : 0; 811344f0eee88ff00398ff7f715fab053374d808c90dSteve Block double normalized_bytes = source_size_in_kb > 0 811444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? total_size_ / source_size_in_kb 811544f0eee88ff00398ff7f715fab053374d808c90dSteve Block : 0; 811644f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%30s - %7.3f ms %7.3f bytes\n", "Sum", 811744f0eee88ff00398ff7f715fab053374d808c90dSteve Block normalized_time, normalized_bytes); 8118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("---------------------------------------------------------------\n"); 8119b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n", 8120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "Total", 8121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<double>(total_) / 1000, 8122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<double>(total_) / full_code_gen_); 8123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8126b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) { 8127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (name == HPhase::kFullCodeGen) { 8128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch full_code_gen_ += ticks; 8129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (name == HPhase::kTotal) { 8130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch total_ += ticks; 8131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8132b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch total_size_ += size; 8133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < names_.length(); ++i) { 8134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (names_[i] == name) { 8135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch timing_[i] += ticks; 8136b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch sizes_[i] += size; 8137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 8138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch names_.Add(name); 8141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch timing_.Add(ticks); 8142b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch sizes_.Add(size); 8143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kFullCodeGen = "Full code generator"; 8148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kTotal = "Total"; 8149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::Begin(const char* name, 8152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph, 8153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LChunk* chunk, 8154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LAllocator* allocator) { 8155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch name_ = name; 8156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_ = graph; 8157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk_ = chunk; 8158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch allocator_ = allocator; 8159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator != NULL && chunk_ == NULL) { 8160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk_ = allocator->chunk(); 8161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 816244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_hydrogen_stats) start_ = OS::Ticks(); 8163b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch start_allocation_size_ = Zone::allocation_size_; 8164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::End() const { 816844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_hydrogen_stats) { 8169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int64_t end = OS::Ticks(); 8170b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch unsigned size = Zone::allocation_size_ - start_allocation_size_; 8171b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch HStatistics::Instance()->SaveTiming(name_, end - start_, size); 8172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 81743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Produce trace output if flag is set so that the first letter of the 81753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // phase name matches the command line parameter FLAG_trace_phase. 81763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_trace_hydrogen && 81773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL) { 8178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_); 8179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_); 8180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator_ != NULL) { 8181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HTracer::Instance()->TraceLiveRanges(name_, allocator_); 8182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 81863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (graph_ != NULL) graph_->Verify(false); // No full verify. 8187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator_ != NULL) allocator_->Verify(); 8188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 8189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} } // namespace v8::internal 8192