hydrogen.cc revision 5d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0b
1c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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), 735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch is_deoptimizing_(false), 745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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()); 1005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 168592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HBasicBlock::Goto(HBasicBlock* block, bool drop_extra) { 16944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (block->IsInlineReturnTarget()) { 1708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HLeaveInlined); 171c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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 179592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HBasicBlock::AddLeaveInlined(HValue* return_value, 180592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* target, 181592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool drop_extra) { 18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(target->IsInlineReturnTarget()); 18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(return_value != NULL); 1848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HLeaveInlined); 185c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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 3195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HBasicBlock::AssignLoopSuccessorDominators() { 3205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Mark blocks that dominate all subsequent reachable blocks inside their 3215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // loop. Exploit the fact that blocks are sorted in reverse post order. When 3225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // the loop is visited in increasing block id order, if the number of 3235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // non-loop-exiting successor edges at the dominator_candidate block doesn't 3245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // exceed the number of previously encountered predecessor edges, there is no 3255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // path from the loop header to any block with higher id that doesn't go 3265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // through the dominator_candidate block. In this case, the 3275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // dominator_candidate block is guaranteed to dominate all blocks reachable 3285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // from it with higher ids. 3295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* last = loop_information()->GetLastBackEdge(); 3305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int outstanding_successors = 1; // one edge from the pre-header 3315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Header always dominates everything. 3325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch MarkAsLoopSuccessorDominator(); 3335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (int j = block_id(); j <= last->block_id(); ++j) { 3345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* dominator_candidate = graph_->blocks()->at(j); 3355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (HPredecessorIterator it(dominator_candidate); !it.Done(); 3365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch it.Advance()) { 3375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* predecessor = it.Current(); 3385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Don't count back edges. 3395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (predecessor->block_id() < dominator_candidate->block_id()) { 3405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch outstanding_successors--; 3415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 3425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 3435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 3445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // If more successors than predecessors have been seen in the loop up to 3455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // now, it's not possible to guarantee that the current block dominates 3465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // all of the blocks with higher IDs. In this case, assume conservatively 3475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // that those paths through loop that don't go through the current block 3485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // contain all of the loop's dependencies. Also be careful to record 3495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // dominator information about the current loop that's being processed, 3505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // and not nested loops, which will be processed when 3515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // AssignLoopSuccessorDominators gets called on their header. 3525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(outstanding_successors >= 0); 3535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header(); 3545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (outstanding_successors == 0 && 3555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) { 3565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch dominator_candidate->MarkAsLoopSuccessorDominator(); 3575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 3585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HControlInstruction* end = dominator_candidate->end(); 3595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (HSuccessorIterator it(end); !it.Done(); it.Advance()) { 3605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* successor = it.Current(); 3615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Only count successors that remain inside the loop and don't loop back 3625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // to a loop header. 3635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (successor->block_id() > dominator_candidate->block_id() && 3645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch successor->block_id() <= last->block_id()) { 3655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Backwards edges must land on loop headers. 3665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(successor->block_id() > dominator_candidate->block_id() || 3675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch successor->IsLoopHeader()); 3685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch outstanding_successors++; 3695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 3705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 3715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 3725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 3735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 3745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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), 4495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 484592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 535592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (do_full_verify) { 536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check that the graph is fully connected. 537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL); 538592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(analyzer.visited_count() == blocks_.length()); 539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 540592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check that entry block dominator is NULL. 541592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(entry_block_->dominator() == NULL); 542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check dominators. 544592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (int i = 0; i < blocks_.length(); ++i) { 545592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* block = blocks_.at(i); 546592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (block->dominator() == NULL) { 547592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Only start block may have no dominator assigned to. 548592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(i == 0); 549592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 550592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Assert that block is unreachable if dominator must not be visited. 551592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ReachabilityAnalyzer dominator_analyzer(entry_block_, 552592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch blocks_.length(), 553592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch block->dominator()); 554592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id())); 555592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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), 6035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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(); 6855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (values > LUnallocated::kMaxVirtualRegisters) { 686c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (FLAG_trace_bailout) { 6875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintF("Not enough virtual registers for (values).\n"); 688c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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 6965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!allocator.Allocate(chunk)) { 6975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (FLAG_trace_bailout) { 6985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintF("Not enough virtual registers (regalloc).\n"); 6995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 7005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return Handle<Code>::null(); 7015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MacroAssembler assembler(info->isolate(), NULL, 0); 704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LCodeGen generator(chunk, &assembler, info); 705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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; 7335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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() { 7465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HPhase phase("H_Block ordering"); 7475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 { 792592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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() { 8085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HPhase phase("H_Assign dominators", this); 809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 8105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* block = blocks_[i]; 8115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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. 8145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch block->AssignCommonDominator(block->predecessors()->first()); 8155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch block->AssignLoopSuccessorDominators(); 816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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() { 8275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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() { 8405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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() { 8745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 917592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 930592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 945592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HGraph::CollectPhis() { 946592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int block_count = blocks_.length(); 947592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch phi_list_ = new ZoneList<HPhi*>(block_count); 948592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (int i = 0; i < block_count; ++i) { 949592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 950592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HPhi* phi = blocks_[i]->phis()->at(j); 951592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch phi_list_->Add(phi); 952592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 953592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 954592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 955592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InferTypes(ZoneList<HValue*>* worklist) { 9585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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: 9825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch explicit HRangeAnalysis(HGraph* graph) : 9835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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_; 9975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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() { 10135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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. 10845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new_range = range->Copy(zone_); 1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::LT || op == Token::LTE) { 10865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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) { 10915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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()) { 11065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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(); 11275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 1168c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochvoid HValueMap::Kill(GVNFlagSet flags) { 1169c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch GVNFlagSet depends_flags = HValue::ConvertChangesToDependsFlags(flags); 1170c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (!present_flags_.ContainsAnyOf(depends_flags)) return; 1171c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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; 1180c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HValue* value = lists_[current].value; 1181c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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; 1190c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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. 1196c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch value = array_[i].value; 1197c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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 { 1209c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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), 1411592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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)); 1416c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch block_side_effects_.AddBlock(GVNFlagSet(), graph_->blocks()->length()); 1417c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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 1423592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Returns true if values with side effects are removed. 1424592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool Analyze(); 1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1427c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock( 1428c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HBasicBlock* dominator, 1429c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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, 14355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch GVNFlagSet loop_kills, 14365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch GVNFlagSet* accumulated_first_time_depends, 14375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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_; 1447592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool removed_side_effects_; 1448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A map of block IDs to their side effects. 1450c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ZoneList<GVNFlagSet> block_side_effects_; 1451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A map of loop header block IDs to their loop's side effects. 1453c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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 1461592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochbool HGlobalValueNumberer::Analyze() { 14625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 1469592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return removed_side_effects_; 1470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ComputeBlockSideEffects() { 14745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // The Analyze phase of GVN can be called multiple times. Clear loop side 14755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // effects before computing them to erase the contents from previous Analyze 14765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // passes. 14775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (int i = 0; i < loop_side_effects_.length(); ++i) { 14785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch loop_side_effects_[i].RemoveAll(); 14795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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(); 1485c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch GVNFlagSet side_effects; 1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1487c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch side_effects.Add(instr->ChangesFlags()); 14885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (instr->IsSoftDeoptimize()) { 14895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch block_side_effects_[id].RemoveAll(); 14905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch side_effects.RemoveAll(); 14915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch break; 14925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 1493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 1494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1495c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch block_side_effects_[id].Add(side_effects); 1496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Loop headers are part of their loop. 1498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1499c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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(); 1505c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch loop_side_effects_[header_id].Add(block->IsLoopHeader() 1506c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ? loop_side_effects_[id] 1507c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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()) { 1517c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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(), 1520c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch side_effects.ToIntegral()); 1521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 15225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch GVNFlagSet accumulated_first_time_depends; 15235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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) { 15265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects, 15275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch &accumulated_first_time_depends, 15285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch &accumulated_first_time_changes); 1529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 15355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGlobalValueNumberer::ProcessLoopBlock( 15365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* block, 15375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* loop_header, 15385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch GVNFlagSet loop_kills, 15395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch GVNFlagSet* first_time_depends, 15405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch GVNFlagSet* first_time_changes) { 1541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* pre_header = loop_header->predecessors()->at(0); 1542c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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(), 1545c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch depends_flags.ToIntegral()); 1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* next = instr->next(); 15495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch bool hoisted = false; 15505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (instr->CheckFlag(HValue::kUseGVN)) { 15515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch TraceGVN("Checking instruction %d (%s) instruction GVN flags 0x%X, " 15525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch "loop kills 0x%X\n", 1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->id(), 15545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch instr->Mnemonic(), 15555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch instr->gvn_flags().ToIntegral(), 15565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch depends_flags.ToIntegral()); 15575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch bool can_hoist = !instr->gvn_flags().ContainsAnyOf(depends_flags); 15585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (instr->IsTransitionElementsKind()) { 15595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // It's possible to hoist transitions out of a loop as long as the 15605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // hoisting wouldn't move the transition past a DependsOn of one of it's 15615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // changes or any instructions that might change an objects map or 15625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // elements contents. 15635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch GVNFlagSet changes = instr->ChangesFlags(); 15645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch GVNFlagSet hoist_depends_blockers = 15655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue::ConvertChangesToDependsFlags(changes); 15665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // In addition to not hoisting transitions above other instructions that 15675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // change dependencies that the transition changes, it must not be 15685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // hoisted above map changes and stores to an elements backing store 15695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // that the transition might change. 15705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch GVNFlagSet hoist_change_blockers = changes; 15715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch hoist_change_blockers.Add(kChangesMaps); 15725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HTransitionElementsKind* trans = HTransitionElementsKind::cast(instr); 15735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (trans->original_map()->has_fast_double_elements()) { 15745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch hoist_change_blockers.Add(kChangesDoubleArrayElements); 15755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 15765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (trans->transitioned_map()->has_fast_double_elements()) { 15775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch hoist_change_blockers.Add(kChangesArrayElements); 1578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 15795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch TraceGVN("Checking dependencies on HTransitionElementsKind %d (%s) " 15805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch "hoist depends blockers 0x%X, hoist change blockers 0x%X, " 15815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch "accumulated depends 0x%X, accumulated changes 0x%X\n", 15825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch instr->id(), 15835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch instr->Mnemonic(), 15845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch hoist_depends_blockers.ToIntegral(), 15855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch hoist_change_blockers.ToIntegral(), 15865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch first_time_depends->ToIntegral(), 15875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch first_time_changes->ToIntegral()); 15885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // It's possible to hoist transition from the current loop loop only if 15895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // they dominate all of the successor blocks in the same loop and there 15905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // are not any instructions that have Changes/DependsOn that intervene 15915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // between it and the beginning of the loop header. 15925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch bool in_nested_loop = block != loop_header && 15935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ((block->parent_loop_header() != loop_header) || 15945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch block->IsLoopHeader()); 15955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch can_hoist = !in_nested_loop && 15965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch block->IsLoopSuccessorDominator() && 15975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch !first_time_depends->ContainsAnyOf(hoist_depends_blockers) && 15985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch !first_time_changes->ContainsAnyOf(hoist_change_blockers); 1599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 16015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (can_hoist) { 16025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch bool inputs_loop_invariant = true; 16035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (int i = 0; i < instr->OperandCount(); ++i) { 16045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { 16055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch inputs_loop_invariant = false; 16065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 16075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 16085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 16095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { 16105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch TraceGVN("Hoisting loop invariant instruction %d\n", instr->id()); 16115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Move the instruction out of the loop. 16125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch instr->Unlink(); 16135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch instr->InsertBefore(pre_header->end()); 16145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (instr->HasSideEffects()) removed_side_effects_ = true; 16155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch hoisted = true; 16165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 16195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!hoisted) { 16205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // If an instruction is not hoisted, we have to account for its side 16215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // effects when hoisting later HTransitionElementsKind instructions. 16225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch first_time_depends->Add(instr->DependsOnFlags()); 16235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch first_time_changes->Add(instr->ChangesFlags()); 16245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 1643c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben MurdochGVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock( 1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* dominator, HBasicBlock* dominated) { 1645c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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())) { 1651c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch side_effects.Add(block_side_effects_[block->block_id()]); 1652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (block->IsLoopHeader()) { 1653c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch side_effects.Add(loop_side_effects_[block->block_id()]); 1654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1655c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch side_effects.Add(CollectSideEffectsOnPathsToDominatedBlock( 1656c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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(); 1677c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch GVNFlagSet flags = instr->ChangesFlags(); 1678c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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()); 1682592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 1683592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (instr->CheckFlag(HValue::kUseGVN)) { 1684592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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()); 1693592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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) 17295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch : graph_(graph), 17305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch worklist_(8), 17315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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()) { 17695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (FLAG_trace_representation) { 17705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintF("Changing #%d representation %s -> %s based on inputs\n", 17715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current->id(), 17725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch r.Mnemonic(), 17735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch inferred.Mnemonic()); 17745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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)) { 18025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (FLAG_trace_representation) { 18035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintF("Changing #%d representation %s -> %s based on uses\n", 18045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch value->id(), 18055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch r.Mnemonic(), 18065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new_rep.Mnemonic()); 18075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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]); 18245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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. 1837592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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() { 18515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 18605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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() { 19305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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) { 2032592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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() { 20675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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; 20865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!phi->CheckUsesForFlag(HValue::kTruncatingToInt32)) { 20875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch phi->ClearFlag(HValue::kTruncatingToInt32); 20885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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() { 21235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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() { 21455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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, 2172592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch TypeFeedbackOracle* oracle, 21735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ReturnHandlingFlag return_handling) 2174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : owner_(owner), 2175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch compilation_info_(info), 2176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch oracle_(oracle), 2177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch call_context_(NULL), 21785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 22215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 || 2235c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch (owner()->environment()->length() == original_length_ && 22365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 || 2243c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch (owner()->environment()->length() == original_length_ + 1 && 22445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 2271592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id); 2272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid EffectContext::ReturnControl(HControlInstruction* instr, int ast_id) { 2276592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 2294592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (instr->HasObservableSideEffects()) owner()->AddSimulate(ast_id); 2295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid ValueContext::ReturnControl(HControlInstruction* instr, int ast_id) { 2299592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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). 2324592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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) { 2334592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 2340592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch empty_true->Goto(if_true(), owner()->function_state()->drop_extra()); 2341592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 2362592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch empty_true->Goto(if_true(), owner()->function_state()->drop_extra()); 2363592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 { 24495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 } 24575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (scope->calls_eval()) { 24585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Bailout("function calls eval"); 24595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return NULL; 24605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 2461c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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) { 24875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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(); 2508592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2509592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#ifdef DEBUG 2510592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Do a full verify after building the graph and computing dominators. 2511592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch graph()->Verify(true); 2512592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#endif 2513592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 251469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch graph()->PropagateDeoptimizingMark(); 2515592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!graph()->CheckConstPhiUses()) { 2516592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Bailout("Unsupported phi use of const variable"); 2517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return NULL; 2518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2519592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch graph()->EliminateRedundantPhis(); 2520592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!graph()->CheckArgumentsPhiUses()) { 2521592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Bailout("Unsupported phi use of arguments"); 2522589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return NULL; 2523589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 2524592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); 2525592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch graph()->CollectPhis(); 2526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 25275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (graph()->has_osr_loop_entry()) { 25285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch const ZoneList<HPhi*>* phis = graph()->osr_loop_entry()->phis(); 25295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (int j = 0; j < phis->length(); j++) { 25305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HPhi* phi = phis->at(j); 25315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch graph()->osr_values()->at(phi->merged_index())->set_incoming_value(phi); 25325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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) { 25465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HPhase phase("H_Global value numbering", graph()); 2547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HGlobalValueNumberer gvn(graph(), info()); 2548592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool removed_side_effects = gvn.Analyze(); 2549592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Trigger a second analysis pass to further eliminate duplicate values that 2550592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // could only be discovered by removing side-effect-generating instructions 2551592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // during the first pass. 2552592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (FLAG_smi_only_arrays && removed_side_effects) { 25535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch removed_side_effects = gvn.Analyze(); 25545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(!removed_side_effects); 2555592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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() { 25795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 26195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochtemplate <class Instruction> 26205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 2634c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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 26405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HArgumentsObject* object = new(zone()) HArgumentsObject; 26415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddInstruction(object); 26425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch graph()->SetArgumentsObject(object); 26435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 } 26705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 26715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->Bind(scope->arguments(), 26725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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, 27765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch BreakType type, 27775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int* drop_extra) { 27785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch *drop_extra = 0; 2779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueScope* current = this; 2780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (current != NULL && current->info()->target() != stmt) { 27815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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). 27855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 27865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (type == BREAK) { 27875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch *drop_extra += current->info()->drop_extra(); 27885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 27895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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()); 28175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int drop_extra = 0; 28185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* continue_block = break_scope()->Get(stmt->target(), 28195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CONTINUE, 28205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch &drop_extra); 28215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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()); 28315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int drop_extra = 0; 28325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* break_block = break_scope()->Get(stmt->target(), 28335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch BREAK, 28345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch &drop_extra); 28355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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)); 28515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else if (function_state()->is_construct()) { 28525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Return from an inlined construct call. In a test context the return 28535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // value will always evaluate to true, in a value context the return value 28545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // needs to be a JSObject. 28555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (context->IsTest()) { 28565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch TestContext* test = TestContext::cast(context); 28575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_ALIVE(VisitForEffect(stmt->expression())); 28585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_block()->Goto(test->if_true(), function_state()->drop_extra()); 28595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else if (context->IsEffect()) { 28605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_ALIVE(VisitForEffect(stmt->expression())); 28615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_block()->Goto(function_return(), function_state()->drop_extra()); 28625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else { 28635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(context->IsValue()); 28645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_ALIVE(VisitForValue(stmt->expression())); 28655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* return_value = Pop(); 28665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* receiver = environment()->Lookup(0); 28675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HHasInstanceTypeAndBranch* typecheck = 28685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HHasInstanceTypeAndBranch(return_value, 28695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch FIRST_SPEC_OBJECT_TYPE, 28705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch LAST_SPEC_OBJECT_TYPE); 28715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* if_spec_object = graph()->CreateBasicBlock(); 28725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* not_spec_object = graph()->CreateBasicBlock(); 28735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch typecheck->SetSuccessorAt(0, if_spec_object); 28745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch typecheck->SetSuccessorAt(1, not_spec_object); 28755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_block()->Finish(typecheck); 28765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if_spec_object->AddLeaveInlined(return_value, 28775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch function_return(), 28785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch function_state()->drop_extra()); 28795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch not_spec_object->AddLeaveInlined(receiver, 28805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch function_return(), 28815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch function_state()->drop_extra()); 28825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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())); 2893592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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())); 28975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* return_value = Pop(); 2898592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch current_block()->AddLeaveInlined(return_value, 2899592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch function_return(), 2900592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch function_state()->drop_extra()); 2901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 29035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 2928592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* context = environment()->LookupContext(); 2929592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 2935592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch SwitchType switch_type = UNKNOWN_SWITCH; 2936592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2937592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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; 2941592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2942592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (switch_type == UNKNOWN_SWITCH) { 2943592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (clause->label()->IsSmiLiteral()) { 2944592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch switch_type = SMI_SWITCH; 2945592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else if (clause->label()->IsStringLiteral()) { 2946592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch switch_type = STRING_SWITCH; 2947592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 2948592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return Bailout("SwitchStatement: non-literal switch label"); 2949592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 2950592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else if ((switch_type == STRING_SWITCH && 2951592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch !clause->label()->IsStringLiteral()) || 2952592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch (switch_type == SMI_SWITCH && 2953592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch !clause->label()->IsSmiLiteral())) { 2954592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return Bailout("SwitchStatemnt: mixed label types are not supported"); 2955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 2957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2958592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HUnaryControlInstruction* string_check = NULL; 2959592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* not_string_block = NULL; 2960592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2961592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Test switch's tag value if all clauses are string literals 2962592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (switch_type == STRING_SWITCH) { 2963592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch string_check = new(zone()) HIsStringAndBranch(tag_value); 2964592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch first_test_block = graph()->CreateBasicBlock(); 2965592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch not_string_block = graph()->CreateBasicBlock(); 2966592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2967592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch string_check->SetSuccessorAt(0, first_test_block); 2968592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch string_check->SetSuccessorAt(1, not_string_block); 2969592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch current_block()->Finish(string_check); 2970592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2971592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch set_current_block(first_test_block); 2972592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 2973592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2974592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // 2. Build all the tests, with dangling true branches 2975592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int default_id = AstNode::kNoNumber; 2976592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (int i = 0; i < clause_count; ++i) { 2977592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CaseClause* clause = clauses->at(i); 2978592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (clause->is_default()) { 2979592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch default_id = clause->EntryId(); 2980592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch continue; 2981592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 2982592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (switch_type == SMI_SWITCH) { 2983592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch clause->RecordTypeFeedback(oracle()); 2984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Generate a compare and branch. 2987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(clause->label())); 298844f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* label_value = Pop(); 2989592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 299044f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 2991592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* body_block = graph()->CreateBasicBlock(); 2992592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2993592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HControlInstruction* compare; 2994592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 2995592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (switch_type == SMI_SWITCH) { 2996592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!clause->IsSmiCompare()) { 2997592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Finish with deoptimize and add uses of enviroment values to 2998592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // account for invisible uses. 2999592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch current_block()->FinishExitWithDeoptimization(HDeoptimize::kUseAll); 3000592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch set_current_block(NULL); 3001592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch break; 3002592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3003592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3004592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HCompareIDAndBranch* compare_ = 3005592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch new(zone()) HCompareIDAndBranch(tag_value, 3006592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch label_value, 3007592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Token::EQ_STRICT); 3008592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch compare_->SetInputRepresentation(Representation::Integer32()); 3009592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch compare = compare_; 3010592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 3011592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch compare = new(zone()) HStringCompareAndBranch(context, tag_value, 3012592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch label_value, 3013592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Token::EQ_STRICT); 3014592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3015592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 30163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch compare->SetSuccessorAt(0, body_block); 30173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch compare->SetSuccessorAt(1, next_test_block); 30183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->Finish(compare); 3019592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 3027592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (not_string_block != NULL) { 3028592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int join_id = (default_id != AstNode::kNoNumber) 3029592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ? default_id 3030592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch : stmt->ExitId(); 3031592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch last_block = CreateJoin(last_block, not_string_block, join_id); 3032592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3033592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3034592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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; 3038592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 31075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { 31085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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(); 31215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int first_expression_index = environment()->first_expression_index(); 31225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int length = environment()->length(); 31235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ZoneList<HUnknownOSRValue*>* osr_values = 31245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) ZoneList<HUnknownOSRValue*>(length); 31255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 31265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 31305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch osr_values->Add(osr_value); 31315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 31325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 31335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (first_expression_index != length) { 31345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->Drop(length - first_expression_index); 31355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (int i = first_expression_index; i < length; ++i) { 31365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HUnknownOSRValue* osr_value = new(zone()) HUnknownOSRValue; 31375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddInstruction(osr_value); 31385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->Push(osr_value); 31395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch osr_values->Add(osr_value); 31405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 3141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch graph()->set_osr_values(osr_values); 31445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 31535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 31775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 31815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 32205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 32245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (osr_entry) graph()->set_osr_loop_entry(loop_entry); 32255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 32675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 32715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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()); 33155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!FLAG_optimize_for_in) { 33175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return Bailout("ForInStatement optimization is disabled"); 33185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 33195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!oracle()->IsForInFastCase(stmt)) { 33215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return Bailout("ForInStatement is not fast case"); 33225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 33235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!stmt->each()->IsVariableProxy() || 33255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) { 33265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return Bailout("ForInStatement with non-local each variable"); 33275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 33285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Variable* each_var = stmt->each()->AsVariableProxy()->var(); 33305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_ALIVE(VisitForValue(stmt->enumerable())); 33325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* enumerable = Top(); // Leave enumerable at the top. 33335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* map = AddInstruction(new(zone()) HForInPrepareMap( 33355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->LookupContext(), enumerable)); 33365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddSimulate(stmt->PrepareId()); 33375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* array = AddInstruction( 33395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HForInCacheArray( 33405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch enumerable, 33415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch map, 33425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch DescriptorArray::kEnumCacheBridgeCacheIndex)); 33435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* array_length = AddInstruction( 33455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HFixedArrayBaseLength(array)); 33465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* start_index = AddInstruction(new(zone()) HConstant( 33485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<Object>(Smi::FromInt(0)), Representation::Integer32())); 33495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Push(map); 33515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Push(array); 33525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Push(array_length); 33535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Push(start_index); 33545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* index_cache = AddInstruction( 33565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HForInCacheArray( 33575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch enumerable, 33585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch map, 33595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch DescriptorArray::kEnumCacheBridgeIndicesCacheIndex)); 33605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HForInCacheArray::cast(array)->set_index_cache( 33615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HForInCacheArray::cast(index_cache)); 33625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch bool osr_entry = PreProcessOsrEntry(stmt); 33645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 33655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_block()->Goto(loop_entry); 33665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch set_current_block(loop_entry); 33675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (osr_entry) graph()->set_osr_loop_entry(loop_entry); 33685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* index = environment()->ExpressionStackAt(0); 33705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* limit = environment()->ExpressionStackAt(1); 33715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Check that we still have more keys. 33735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HCompareIDAndBranch* compare_index = 33745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HCompareIDAndBranch(index, limit, Token::LT); 33755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch compare_index->SetInputRepresentation(Representation::Integer32()); 33765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* loop_body = graph()->CreateBasicBlock(); 33785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* loop_successor = graph()->CreateBasicBlock(); 33795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch compare_index->SetSuccessorAt(0, loop_body); 33815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch compare_index->SetSuccessorAt(1, loop_successor); 33825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_block()->Finish(compare_index); 33835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch set_current_block(loop_successor); 33855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Drop(5); 33865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch set_current_block(loop_body); 33885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* key = AddInstruction( 33905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HLoadKeyedFastElement( 33915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->ExpressionStackAt(2), // Enum cache. 33925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->ExpressionStackAt(0), // Iteration index. 33935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HLoadKeyedFastElement::OMIT_HOLE_CHECK)); 33945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 33955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Check if the expected map still matches that of the enumerable. 33965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // If not just deoptimize. 33975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddInstruction(new(zone()) HCheckMapValue( 33985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->ExpressionStackAt(4), 33995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->ExpressionStackAt(3))); 34005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 34015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Bind(each_var, key); 34025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 34035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch BreakAndContinueInfo break_info(stmt, 5); 34045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry, &break_info)); 34055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 34065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* body_exit = 34075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch JoinContinue(stmt, current_block(), break_info.continue_block()); 34085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 34095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (body_exit != NULL) { 34105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch set_current_block(body_exit); 34115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 34125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* current_index = Pop(); 34135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* new_index = new(zone()) HAdd(environment()->LookupContext(), 34145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_index, 34155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch graph()->GetConstant1()); 34165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new_index->AssumeRepresentation(Representation::Integer32()); 34175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PushAndAdd(new_index); 34185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch body_exit = current_block(); 34195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 34205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 34215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* loop_exit = CreateLoop(stmt, 34225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch loop_entry, 34235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch body_exit, 34245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch loop_successor, 34255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch break_info.break_block()); 34265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 34275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 3548c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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: { 3579c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (variable->mode() == LET || variable->mode() == CONST_HARMONY) { 3580c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return Bailout("reference to global harmony declared variable"); 3581c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 3582592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Handle known global constants like 'undefined' specially to avoid a 3583592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // load from a global cell for them. 3584592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> constant_value = 3585592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch isolate()->factory()->GlobalConstantFor(variable->name()); 3586592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!constant_value.is_null()) { 3587592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HConstant* instr = 3588592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch new(zone()) HConstant(constant_value, Representation::Tagged()); 3589592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 3590592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3591592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3592592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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)); 3604592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HLoadGlobalCell* instr = 3605592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 3624c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (value == graph()->GetConstantHole()) { 3625c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ASSERT(variable->mode() == CONST || 3626c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch variable->mode() == CONST_HARMONY || 3627c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch variable->mode() == LET); 3628c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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); 3635c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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 36695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// Determines whether the given array or object literal boilerplate satisfies 36705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// all limits to be considered for fast deep-copying and computes the total 3671592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch// size of all objects that are part of the graph. 36725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochstatic bool IsFastLiteral(Handle<JSObject> boilerplate, 36735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int max_depth, 36745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int* max_properties, 36755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int* total_size) { 36765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(max_depth >= 0 && *max_properties >= 0); 36775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (max_depth == 0) return false; 3678592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3679c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Handle<FixedArrayBase> elements(boilerplate->elements()); 3680592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (elements->length() > 0 && 36815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch elements->map() != boilerplate->GetHeap()->fixed_cow_array_map()) { 36825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (boilerplate->HasFastDoubleElements()) { 36835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch *total_size += FixedDoubleArray::SizeFor(elements->length()); 36845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else if (boilerplate->HasFastElements()) { 36855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int length = elements->length(); 36865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (int i = 0; i < length; i++) { 36875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if ((*max_properties)-- == 0) return false; 36885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<Object> value = JSObject::GetElement(boilerplate, i); 36895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (value->IsJSObject()) { 36905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<JSObject> value_object = Handle<JSObject>::cast(value); 36915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!IsFastLiteral(value_object, 36925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch max_depth - 1, 36935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch max_properties, 36945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch total_size)) { 36955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return false; 36965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 36975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 36985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 36995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch *total_size += FixedArray::SizeFor(length); 37005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else { 37015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return false; 37025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 3703592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3704592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3705c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Handle<FixedArray> properties(boilerplate->properties()); 3706592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (properties->length() > 0) { 3707592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return false; 3708592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 3709592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int nof = boilerplate->map()->inobject_properties(); 3710592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (int i = 0; i < nof; i++) { 37115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if ((*max_properties)-- == 0) return false; 3712592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> value(boilerplate->InObjectPropertyAt(i)); 3713592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (value->IsJSObject()) { 3714592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> value_object = Handle<JSObject>::cast(value); 37155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!IsFastLiteral(value_object, 37165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch max_depth - 1, 37175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch max_properties, 37185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch total_size)) { 3719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return false; 3720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch *total_size += boilerplate->map()->instance_size(); 3726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return true; 3727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 3728592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3729592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 3733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSFunction> closure = function_state()->compilation_info()->closure(); 3735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 3736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HInstruction* literal; 3737592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check whether to use fast or slow deep-copying for boilerplate. 3739592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int total_size = 0; 37405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int max_properties = HFastLiteral::kMaxLiteralProperties; 3741592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> boilerplate(closure->literals()->get(expr->literal_index())); 3742592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (boilerplate->IsJSObject() && 37435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch IsFastLiteral(Handle<JSObject>::cast(boilerplate), 37445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HFastLiteral::kMaxLiteralDepth, 37455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch &max_properties, 37465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch &total_size)) { 3747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<JSObject> boilerplate_object = Handle<JSObject>::cast(boilerplate); 37485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch literal = new(zone()) HFastLiteral(context, 37495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch boilerplate_object, 37505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch total_size, 37515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->literal_index(), 37525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->depth()); 3753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 37545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch literal = new(zone()) HObjectLiteral(context, 37555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->constant_properties(), 37565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->fast_elements(), 37575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->literal_index(), 37585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->depth(), 37595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->has_function()); 3760592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 3761592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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()) { 37825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch property->RecordTypeFeedback(oracle()); 3783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(value)); 3784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 37855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* store = BuildStoreNamed(literal, value, property); 37861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(store); 37875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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(); 38245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* literal; 3825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3826c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Handle<FixedArray> literals(environment()->closure()->literals()); 3827c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Handle<Object> raw_boilerplate(literals->get(expr->literal_index())); 3828c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 3829c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (raw_boilerplate->IsUndefined()) { 3830c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch raw_boilerplate = Runtime::CreateArrayLiteralBoilerplate( 3831c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch isolate(), literals, expr->constant_elements()); 3832c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (raw_boilerplate.is_null()) { 3833c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return Bailout("array boilerplate creation failed"); 3834c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 3835c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch literals->set(expr->literal_index(), *raw_boilerplate); 3836c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (JSObject::cast(*raw_boilerplate)->elements()->map() == 3837c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch isolate()->heap()->fixed_cow_array_map()) { 3838c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch isolate()->counters()->cow_arrays_created_runtime()->Increment(); 3839c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 3840c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 3841c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 3842c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Handle<JSObject> boilerplate = Handle<JSObject>::cast(raw_boilerplate); 3843c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ElementsKind boilerplate_elements_kind = 3844c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Handle<JSObject>::cast(boilerplate)->GetElementsKind(); 3845c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 38465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Check whether to use fast or slow deep-copying for boilerplate. 38475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int total_size = 0; 38485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int max_properties = HFastLiteral::kMaxLiteralProperties; 38495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (IsFastLiteral(boilerplate, 38505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HFastLiteral::kMaxLiteralDepth, 38515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch &max_properties, 38525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch &total_size)) { 38535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch literal = new(zone()) HFastLiteral(context, 38545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch boilerplate, 38555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch total_size, 38565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->literal_index(), 38575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->depth()); 38585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else { 38595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch literal = new(zone()) HArrayLiteral(context, 38605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch boilerplate, 38615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch length, 38625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->literal_index(), 38635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->depth()); 38645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 3882592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch elements = new(zone()) HLoadElements(literal); 3883592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch AddInstruction(elements); 3884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 38858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValue* key = AddInstruction( 38868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), 38878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Representation::Integer32())); 3888592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 3889c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch switch (boilerplate_elements_kind) { 3890c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case FAST_SMI_ONLY_ELEMENTS: 3891c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Smi-only arrays need a smi check. 3892c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckSmi(value)); 3893c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Fall through. 3894c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case FAST_ELEMENTS: 3895c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HStoreKeyedFastElement( 3896c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch elements, 3897c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch key, 3898c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch value, 3899c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch boilerplate_elements_kind)); 3900c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch break; 3901c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3902c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HStoreKeyedFastDoubleElement(elements, 3903c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch key, 3904c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch value)); 3905c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch break; 3906c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch default: 3907c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch UNREACHABLE(); 3908c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch break; 3909c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 3910592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 3922c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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)); 3950c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckMap(object, type, NULL, 3951c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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. 3971c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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, 3986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch function_strict_mode_flag()); 3987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, 3991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 39925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ObjectLiteral::Property* prop) { 39935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Literal* key = prop->key()->AsLiteral(); 39945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<String> name = Handle<String>::cast(key->handle()); 39955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(!name.is_null()); 39965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 39975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch LookupResult lookup(isolate()); 39985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<Map> type = prop->GetReceiverType(); 39995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch bool is_monomorphic = prop->IsMonomorphic() && 40005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ComputeStoredField(type, name, &lookup); 40015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 40025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return is_monomorphic 40035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ? BuildStoreNamedField(object, name, value, type, &lookup, 40045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch true) // Needs smi and map check. 40055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 4019592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 4043592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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). 4086592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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(); 4126592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 4159592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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) { 4171592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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)); 4176592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HInstruction* instr = 4177592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch new(zone()) HStoreGlobalCell(value, cell, lookup.GetPropertyDetails()); 41788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr->set_position(position); 41798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(instr); 4180592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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, 4190592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch function_strict_mode_flag()); 41918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr->set_position(position); 41928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(instr); 4193592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(instr->HasObservableSideEffects()); 4194592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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(); 4211c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (var->mode() == LET) { 4212c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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: 4227c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (var->mode() == CONST) { 4228c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return Bailout("unsupported const compound assignment"); 4229c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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 4250c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HStoreContextSlot::Mode mode; 4251c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 4252c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch switch (var->mode()) { 4253c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case LET: 4254c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mode = HStoreContextSlot::kCheckDeoptimize; 4255c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch break; 4256c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case CONST: 4257c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return ast_context()->ReturnValue(Pop()); 4258c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case CONST_HARMONY: 4259c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // This case is checked statically so no need to 4260c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // perform checks here 4261c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch UNREACHABLE(); 4262c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch default: 4263c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mode = HStoreContextSlot::kNoCheck; 4264c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 4265c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 4266589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = BuildContextChainWalk(var); 4267589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HStoreContextSlot* instr = 4268c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch new(zone()) HStoreContextSlot(context, var->index(), mode, Top()); 4269589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddInstruction(instr); 4270592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (instr->HasObservableSideEffects()) { 4271592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch AddSimulate(expr->AssignmentId()); 4272592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 4298592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 4306592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 4313592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 4338592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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(); 4377c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 4378592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (var->mode() == CONST) { 43793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (expr->op() != Token::INIT_CONST) { 4380c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 4381c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return ast_context()->ReturnValue(Pop()); 4382c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 4383c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 4384c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (var->IsStackAllocated()) { 4385c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // We insert a use of the old value to detect unsupported uses of const 4386c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // variables (e.g. initialization inside a loop). 4387c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HValue* old_value = environment()->Lookup(var); 4388c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new HUseConst(old_value)); 43893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4390c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } else if (var->mode() == CONST_HARMONY) { 4391c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (expr->op() != Token::INIT_CONST_HARMONY) { 4392c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return Bailout("non-initializer assignment to const"); 43933fb3ca8c7ca439d408449a395897395c0faae8d1Ben 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: { 4410c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Perform an initialization check for let declared variables 4411c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // or parameters. 4412c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (var->mode() == LET && expr->op() == Token::ASSIGN) { 4413c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HValue* env_value = environment()->Lookup(var); 4414c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (env_value == graph()->GetConstantHole()) { 4415c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return Bailout("assignment to let variable before initialization"); 4416c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 4417c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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())); 4443c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HStoreContextSlot::Mode mode; 4444c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (expr->op() == Token::ASSIGN) { 4445c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch switch (var->mode()) { 4446c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case LET: 4447c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mode = HStoreContextSlot::kCheckDeoptimize; 4448c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch break; 4449c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case CONST: 4450c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return ast_context()->ReturnValue(Pop()); 4451c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case CONST_HARMONY: 4452c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // This case is checked statically so no need to 4453c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // perform checks here 4454c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch UNREACHABLE(); 4455c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch default: 4456c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mode = HStoreContextSlot::kNoCheck; 4457c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 4458c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } else if (expr->op() == Token::INIT_VAR || 4459c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch expr->op() == Token::INIT_LET || 4460c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch expr->op() == Token::INIT_CONST_HARMONY) { 4461c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mode = HStoreContextSlot::kNoCheck; 4462c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } else { 4463c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ASSERT(expr->op() == Token::INIT_CONST); 4464c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 4465c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch mode = HStoreContextSlot::kCheckIgnoreAssignment; 4466c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 4467c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 4468589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = BuildContextChainWalk(var); 4469c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HStoreContextSlot* instr = new(zone()) HStoreContextSlot( 4470c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch context, var->index(), mode, Top()); 4471589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddInstruction(instr); 4472592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (instr->HasObservableSideEffects()) { 4473592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch AddSimulate(expr->AssignmentId()); 4474592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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)); 4515c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckMap(object, type, NULL, 4516c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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) { 45355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (expr->IsUninitialized() && !FLAG_always_opt) { 45365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddInstruction(new(zone()) HSoftDeoptimize); 45375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_block()->MarkAsDeoptimizing(); 45385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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) { 4550592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch LookupResult lookup(isolate()); 4551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->LookupInDescriptors(NULL, *name, &lookup); 4552c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (lookup.IsFound() && lookup.type() == FIELD) { 4553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return BuildLoadNamedField(obj, 4554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr, 4555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map, 4556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &lookup, 4557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true); 4558c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } else if (lookup.IsFound() && lookup.type() == CONSTANT_FUNCTION) { 45598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(obj)); 4560c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckMap(obj, map, NULL, 4561c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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: { 45875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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: { 45965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!val->representation().IsInteger32()) { 45975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch val = AddInstruction(new(zone()) HChange( 45985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch val, 45995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Representation::Integer32(), 46005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch true, // Truncate to int32. 46015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch false)); // Don't deoptimize undefined (irrelevant here). 46025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 46033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 46043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4605589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 4606589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 46073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 4608592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 { 46195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 4626592a9fc1d8ea420377a2e7efd0600e20b058be2bBen MurdochHInstruction* HGraphBuilder::BuildFastElementAccess(HValue* elements, 4627592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* checked_key, 4628592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* val, 4629592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ElementsKind elements_kind, 4630592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool is_store) { 4631592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (is_store) { 4632592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(val != NULL); 4633c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch switch (elements_kind) { 4634c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case FAST_DOUBLE_ELEMENTS: 4635c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return new(zone()) HStoreKeyedFastDoubleElement( 4636c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch elements, checked_key, val); 4637c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case FAST_SMI_ONLY_ELEMENTS: 4638c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Smi-only arrays need a smi check. 4639c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckSmi(val)); 4640c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Fall through. 4641c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case FAST_ELEMENTS: 4642c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return new(zone()) HStoreKeyedFastElement( 4643c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch elements, checked_key, val, elements_kind); 4644c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch default: 4645c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch UNREACHABLE(); 4646c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return NULL; 4647592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 4648592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 4649592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // It's an element load (!is_store). 4650592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (elements_kind == FAST_DOUBLE_ELEMENTS) { 4651592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return new(zone()) HLoadKeyedFastDoubleElement(elements, checked_key); 4652592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { // FAST_ELEMENTS or FAST_SMI_ONLY_ELEMENTS. 4653592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return new(zone()) HLoadKeyedFastElement(elements, checked_key); 4654592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 4655592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 4656592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 4657592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 46583fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHInstruction* HGraphBuilder::BuildMonomorphicElementAccess(HValue* object, 46593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* key, 46603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* val, 4661592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> map, 46623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_store) { 4663592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HInstruction* mapcheck = AddInstruction(new(zone()) HCheckMap(object, map)); 4664592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool fast_smi_only_elements = map->has_fast_smi_only_elements(); 4665592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch bool fast_elements = map->has_fast_elements(); 466669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 4667592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 } 4682c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ASSERT(fast_smi_only_elements || 4683c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch fast_elements || 4684c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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)); 4691592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return BuildFastElementAccess(elements, checked_key, val, 4692592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 4715592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Elements_kind transition support. 4716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MapHandleList transition_target(maps->length()); 4717592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Collect possible transition targets. 4718592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MapHandleList possible_transitioned_maps(maps->length()); 4719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (int i = 0; i < maps->length(); ++i) { 4720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> map = maps->at(i); 4721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ElementsKind elements_kind = map->elements_kind(); 4722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (elements_kind == FAST_DOUBLE_ELEMENTS || 4723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch elements_kind == FAST_ELEMENTS) { 4724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch possible_transitioned_maps.Add(map); 4725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 4726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 4727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Get transition target for each map (NULL == no transition). 4728592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (int i = 0; i < maps->length(); ++i) { 4729592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> map = maps->at(i); 4730592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> transitioned_map = 4731592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch map->FindTransitionedMap(&possible_transitioned_maps); 4732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch transition_target.Add(transitioned_map); 4733592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 4734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 4735592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch int num_untransitionable_maps = 0; 4736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> untransitionable_map; 47373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i < maps->length(); ++i) { 4738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> map = maps->at(i); 4739592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(map->IsMap()); 4740592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!transition_target.at(i).is_null()) { 47415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddInstruction(new(zone()) HTransitionElementsKind( 4742592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch object, map, transition_target.at(i))); 4743592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 4744592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch type_todo[map->elements_kind()] = true; 4745592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (map->elements_kind() >= FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND) { 4746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch todo_external_array = true; 4747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 4748592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch num_untransitionable_maps++; 4749592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch untransitionable_map = map; 47503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 47513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 47523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // If only one map is left after transitioning, handle this case 4754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // monomorphically. 4755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (num_untransitionable_maps == 1) { 4756c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HInstruction* instr = NULL; 4757c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (untransitionable_map->has_slow_elements_kind()) { 4758c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch instr = AddInstruction(is_store ? BuildStoreKeyedGeneric(object, key, val) 4759c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch : BuildLoadKeyedGeneric(object, key)); 4760c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } else { 4761c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch instr = AddInstruction(BuildMonomorphicElementAccess( 4762c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch object, key, val, untransitionable_map, is_store)); 4763c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 4764592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch *has_side_effects |= instr->HasObservableSideEffects(); 4765592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr->set_position(position); 4766592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return is_store ? NULL : instr; 4767592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 4768592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 4769592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 4779592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Generated code assumes that FAST_SMI_ONLY_ELEMENTS, FAST_ELEMENTS, 4780592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS are handled before external 4781592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // arrays. 4782592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 4783592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STATIC_ASSERT(FAST_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 4784592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STATIC_ASSERT(FAST_DOUBLE_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 4785592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch STATIC_ASSERT(DICTIONARY_ELEMENTS < FIRST_EXTERNAL_ARRAY_ELEMENTS_KIND); 47863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 4787592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (ElementsKind elements_kind = FIRST_ELEMENTS_KIND; 4788589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind <= LAST_ELEMENTS_KIND; 4789589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind = ElementsKind(elements_kind + 1)) { 4790592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // After having handled FAST_ELEMENTS, FAST_SMI_ONLY_ELEMENTS, 4791592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // FAST_DOUBLE_ELEMENTS and DICTIONARY_ELEMENTS, we need to add some code 4792592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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; 4814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS || 4815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch elements_kind == FAST_ELEMENTS || 4816589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind == FAST_DOUBLE_ELEMENTS) { 4817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 } 4822592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // TODO(jkummerow): The need for these two blocks could be avoided 4823592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // in one of two ways: 4824592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // (1) Introduce ElementsKinds for JSArrays that are distinct from 4825592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // those for fast objects. 4826592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // (2) Put the common instructions into a third "join" block. This 4827592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // requires additional AST IDs that we can deopt to from inside 4828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // that join block. They must be added to the Property class (when 4829592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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); 4839592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HInstruction* length; 4840592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch length = AddInstruction(new(zone()) HJSArrayLength(object, typecheck)); 48413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch checked_key = AddInstruction(new(zone()) HBoundsCheck(key, length)); 4842592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch access = AddInstruction(BuildFastElementAccess( 4843592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch elements, checked_key, val, elements_kind, is_store)); 4844592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (!is_store) { 48453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Push(access); 48463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 4847592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 4848592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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)); 4857592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch access = AddInstruction(BuildFastElementAccess( 4858592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 } 4869592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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()) { 4898592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Map> map = expr->GetMonomorphicReceiverType(); 4899c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (map->has_slow_elements_kind()) { 4900c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch instr = is_store ? BuildStoreKeyedGeneric(obj, key, val) 4901c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch : BuildLoadKeyedGeneric(obj, key); 4902c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } else { 4903c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(obj)); 4904c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch instr = BuildMonomorphicElementAccess(obj, key, val, map, is_store); 4905c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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); 4919592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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, 4933592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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; 4986592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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)); 5064c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckMap(receiver, receiver_map, NULL, 5065c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben 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 } 51065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 51765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::TryInline(CallKind call_kind, 51775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<JSFunction> target, 51785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ZoneList<Expression*>* arguments, 51795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* receiver, 51805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int ast_id, 51815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int return_id, 51825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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. 51925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if ((FLAG_limit_inlining && target_shared->SourceSize() > kMaxSourceSize) 51935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 } 52035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (target_shared->dont_inline() || target_shared->dont_optimize()) { 52045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch TraceInline(target, caller, "target contains unsupported syntax [early]"); 52055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return false; 52065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 52075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 52085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int nodes_added = target_shared->ast_node_count(); 52095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) || 52105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch nodes_added > kUnlimitedMaxInlinedSize) { 52115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch TraceInline(target, caller, "target AST is too large [early]"); 52125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return false; 52135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 5214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5215592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#if !defined(V8_TARGET_ARCH_IA32) 5216592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 } 5224592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#endif 5225592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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 } 52355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (env->outer()->frame_type() == JS_FUNCTION) { 5236c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch current_level++; 5237c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 52388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch env = env->outer(); 5239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 5240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Don't inline recursive functions. 5242592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch for (FunctionState* state = function_state(); 5243592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch state != NULL; 5244592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch state = state->outer()) { 5245592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (state->compilation_info()->closure()->shared() == *target_shared) { 5246592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch TraceInline(target, caller, "target is recursive"); 5247592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return false; 5248592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 5249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 5250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't want to add more than a certain number of nodes from inlining. 52525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if ((FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) || 52535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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); 5260592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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(); 52655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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 52775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // The following conditions must be checked again after re-parsing, because 52785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // earlier the information might not have been complete due to lazy parsing. 52795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch nodes_added = function->ast_node_count(); 52805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if ((FLAG_limit_inlining && nodes_added > kMaxInlinedSize) || 52815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch nodes_added > kUnlimitedMaxInlinedSize) { 52825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch TraceInline(target, caller, "target AST is too large [late]"); 52835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return false; 52845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 52855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AstProperties::Flags* flags(function->flags()); 52865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (flags->Contains(kDontInline) || flags->Contains(kDontOptimize)) { 52875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch TraceInline(target, caller, "target contains unsupported syntax [late]"); 5288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 5289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 52915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // If the function uses the arguments object check that inlining of functions 52925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // with arguments object is enabled and the arguments-variable is 52935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // stack allocated. 5294c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (function->scope()->arguments() != NULL) { 52955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!FLAG_inline_arguments) { 52965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch TraceInline(target, caller, "target uses arguments object"); 52975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return false; 52985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 52995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 53005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!function->scope()->arguments()->IsStackAllocated()) { 53015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch TraceInline(target, 53025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch caller, 53035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch "target uses non-stackallocated arguments object"); 53045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return false; 53055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 5306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben 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 } 5328592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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. 5331592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<ScopeInfo> target_scope_info = 5332592a9fc1d8ea420377a2e7efd0600e20b058be2bBen 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()), 5350592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Context>(target->context()->global_context()), 5351592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch isolate()); 5352592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // The function state is new-allocated because we need to delete it 5353592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // in two different places. 53545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch FunctionState* target_state = new FunctionState( 53555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen 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, 53605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch arguments->length(), 5361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch function, 5362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch undefined, 53635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch call_kind, 53645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch function_state()->is_construct()); 5365592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#ifdef V8_TARGET_ARCH_IA32 5366592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // IA32 only, overwrite the caller's context in the deoptimization 5367592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // environment with the correct one. 5368592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // 5369592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // TODO(kmillikin): implement the same inlining on other platforms so we 5370592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // can remove the unsightly ifdefs in this function. 5371592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HConstant* context = new HConstant(Handle<Context>(target->context()), 5372592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Representation::Tagged()); 5373592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch AddInstruction(context); 5374592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch inner_env->BindContext(context); 5375592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch#endif 53765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddSimulate(return_id); 53775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_block()->UpdateEnvironment(inner_env); 5378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(new(zone()) HEnterInlined(target, 53795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch arguments->length(), 5380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch function, 53815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch call_kind, 53825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch function_state()->is_construct())); 53835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // If the function uses arguments object create and bind one. 53845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (function->scope()->arguments() != NULL) { 53855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(function->scope()->arguments()->IsStackAllocated()); 53865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->Bind(function->scope()->arguments(), 53875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch graph()->GetArgumentsObject()); 53885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 53893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch VisitDeclarations(target_info.scope()->declarations()); 539044f0eee88ff00398ff7f715fab053374d808c90dSteve Block VisitStatements(function->body()); 5391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) { 5392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Bail out if the inline function did, as we cannot residualize a call 5393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // instead. 5394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, "inline graph construction failed"); 53955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch target_shared->DisableOptimization(); 5396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inline_bailout_ = true; 5397592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch delete target_state; 5398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 5399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Update inlined nodes count. 5402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inlined_count_ += nodes_added; 5403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceInline(target, caller, NULL); 5405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 540644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (current_block() != NULL) { 54075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Add default return value (i.e. undefined for normals calls or the newly 54085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // allocated receiver for construct calls) if control can fall off the 54095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // body. In a test context, undefined is false and any JSObject is true. 54105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (call_context()->IsValue()) { 5411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(function_return() != NULL); 54125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* return_value = function_state()->is_construct() 54135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ? receiver 54145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch : undefined; 54155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_block()->AddLeaveInlined(return_value, 54165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch function_return(), 54175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch function_state()->drop_extra()); 54185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else if (call_context()->IsEffect()) { 54195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(function_return() != NULL); 54205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_block()->Goto(function_return(), function_state()->drop_extra()); 5421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5422592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(call_context()->IsTest()); 54235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(inlined_test_context() != NULL); 54245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HBasicBlock* target = function_state()->is_construct() 54255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ? inlined_test_context()->if_true() 54265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch : inlined_test_context()->if_false(); 54275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch current_block()->Goto(target, function_state()->drop_extra()); 5428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Fix up the function exits. 5432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (inlined_test_context() != NULL) { 5433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_true = inlined_test_context()->if_true(); 5434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_false = inlined_test_context()->if_false(); 54353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 5436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Pop the return test context from the expression context stack. 54373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(ast_context() == inlined_test_context()); 5438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ClearInlinedTestContext(); 5439592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch delete target_state; 5440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Forward to the real test context. 5442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (if_true->HasPredecessor()) { 54435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if_true->SetJoinId(ast_id); 5444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 5445592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if_true->Goto(true_target, function_state()->drop_extra()); 5446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (if_false->HasPredecessor()) { 54485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if_false->SetJoinId(ast_id); 5449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 5450592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if_false->Goto(false_target, function_state()->drop_extra()); 5451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 5452e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 5453592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return true; 5454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (function_return()->HasPredecessor()) { 54565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch function_return()->SetJoinId(ast_id); 5457e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(function_return()); 5458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 5459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(NULL); 5460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5461592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch delete target_state; 5462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 5463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 54665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::TryInlineCall(Call* expr, bool drop_extra) { 54675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // The function call we are inlining is a method call if the call 54685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // is a property call. 54695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CallKind call_kind = (expr->expression()->AsProperty() == NULL) 54705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ? CALL_AS_FUNCTION 54715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch : CALL_AS_METHOD; 54725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 54735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return TryInline(call_kind, 54745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->target(), 54755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->arguments(), 54765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch NULL, 54775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->id(), 54785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->ReturnId(), 54795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch drop_extra ? DROP_EXTRA_ON_RETURN : NORMAL_RETURN); 54805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 54815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 54825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 54835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::TryInlineConstruct(CallNew* expr, HValue* receiver) { 54845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return TryInline(CALL_AS_FUNCTION, 54855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->target(), 54865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->arguments(), 54875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch receiver, 54885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->id(), 54895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->ReturnId(), 54905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CONSTRUCT_CALL_RETURN); 54915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 54925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 54935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 54945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr, bool drop_extra) { 54955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 54965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 54975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch switch (id) { 54985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch case kMathRound: 54995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch case kMathAbs: 55005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch case kMathSqrt: 55015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch case kMathLog: 55025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch case kMathSin: 55035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch case kMathCos: 55045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch case kMathTan: 55055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (expr->arguments()->length() == 1) { 55065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* argument = Pop(); 55075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* context = environment()->LookupContext(); 55085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Drop(1); // Receiver. 55095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HUnaryMathOperation* op = 55105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HUnaryMathOperation(context, argument, id); 55115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch op->set_position(expr->position()); 55125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (drop_extra) Drop(1); // Optionally drop the function. 55135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ast_context()->ReturnInstruction(op, expr->id()); 55145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return true; 55155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 55165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch break; 55175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch default: 55185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Not supported for inlining yet. 55195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch break; 55205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 55215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return false; 55225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 55235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 55245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 55255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochbool HGraphBuilder::TryInlineBuiltinMethodCall(Call* expr, 55265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* receiver, 55275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<Map> receiver_map, 55285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CheckType check_type) { 55291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); 5530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Try to inline calls like Math.* as operations in the calling function. 55311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 5532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 5533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length() + 1; // Plus receiver. 5534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (id) { 55351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case kStringCharCodeAt: 553644f0eee88ff00398ff7f715fab053374d808c90dSteve Block case kStringCharAt: 55371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (argument_count == 2 && check_type == STRING_CHECK) { 55381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* index = Pop(); 55391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* string = Pop(); 55403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 55411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!expr->holder().is_null()); 55428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckPrototypeMaps( 55431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK), 55441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block expr->holder())); 55453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharCodeAt* char_code = 55463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch BuildStringCharCodeAt(context, string, index); 554744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (id == kStringCharCodeAt) { 554844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ast_context()->ReturnInstruction(char_code, expr->id()); 554944f0eee88ff00398ff7f715fab053374d808c90dSteve Block return true; 555044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 555144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(char_code); 55528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStringCharFromCode* result = 55533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HStringCharFromCode(context, char_code); 55541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ast_context()->ReturnInstruction(result, expr->id()); 55551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return true; 55561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 55571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 5558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathRound: 5559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathFloor: 5560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathAbs: 5561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathSqrt: 5562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathLog: 5563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathSin: 5564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathCos: 55655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch case kMathTan: 55661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 55671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddCheckConstantFunction(expr, receiver, receiver_map, true); 5568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* argument = Pop(); 55693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 5570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(1); // Receiver. 55713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HUnaryMathOperation* op = 55723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HUnaryMathOperation(context, argument, id); 5573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch op->set_position(expr->position()); 5574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(op, expr->id()); 5575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 5576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 5578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathPow: 55791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 55801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddCheckConstantFunction(expr, receiver, receiver_map, true); 5581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 5582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 5583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Pop(); // Pop receiver. 55843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 5585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* result = NULL; 5586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Use sqrt() if exponent is 0.5 or -0.5. 5587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 5588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double exponent = HConstant::cast(right)->DoubleValue(); 5589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (exponent == 0.5) { 55903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result = 55913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HUnaryMathOperation(context, left, kMathPowHalf); 5592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (exponent == -0.5) { 5593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* double_one = 55948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HConstant(Handle<Object>(Smi::FromInt(1)), 55958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Representation::Double()); 5596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(double_one); 5597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HUnaryMathOperation* square_root = 55983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HUnaryMathOperation(context, left, kMathPowHalf); 5599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(square_root); 5600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // MathPowHalf doesn't have side effects so there's no need for 5601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // an environment simulation here. 5602592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(!square_root->HasObservableSideEffects()); 56033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result = new(zone()) HDiv(context, double_one, square_root); 5604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (exponent == 2.0) { 56053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result = new(zone()) HMul(context, left, left); 5606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (right->IsConstant() && 56081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HConstant::cast(right)->HasInteger32Value() && 56091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HConstant::cast(right)->Integer32Value() == 2) { 56103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result = new(zone()) HMul(context, left, left); 5611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 56131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (result == NULL) { 56148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch result = new(zone()) HPower(left, right); 56151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 5616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 5617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 5618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 5620c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case kMathRandom: 5621c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (argument_count == 1 && check_type == RECEIVER_MAP_CHECK) { 5622c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddCheckConstantFunction(expr, receiver, receiver_map, true); 56235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Drop(1); // Receiver. 5624c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HValue* context = environment()->LookupContext(); 5625c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 5626c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(global_object); 5627c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HRandom* result = new(zone()) HRandom(global_object); 5628c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 5629c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return true; 5630c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 5631c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch break; 5632c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case kMathMax: 5633c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch case kMathMin: 5634c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 5635c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddCheckConstantFunction(expr, receiver, receiver_map, true); 5636c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HValue* right = Pop(); 5637c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HValue* left = Pop(); 56385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Pop(); // Pop receiver. 56395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 56405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* left_operand = left; 56415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* right_operand = right; 56425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 56435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // If we do not have two integers, we convert to double for comparison. 56445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!left->representation().IsInteger32() || 56455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch !right->representation().IsInteger32()) { 56465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!left->representation().IsDouble()) { 56475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HChange* left_convert = new(zone()) HChange( 56485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch left, 56495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Representation::Double(), 56505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch false, // Do not truncate when converting to double. 56515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch true); // Deoptimize for undefined. 56525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch left_convert->SetFlag(HValue::kBailoutOnMinusZero); 56535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch left_operand = AddInstruction(left_convert); 56545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 56555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (!right->representation().IsDouble()) { 56565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HChange* right_convert = new(zone()) HChange( 56575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch right, 56585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Representation::Double(), 56595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch false, // Do not truncate when converting to double. 56605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch true); // Deoptimize for undefined. 56615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch right_convert->SetFlag(HValue::kBailoutOnMinusZero); 56625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch right_operand = AddInstruction(right_convert); 56635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 5664c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 5665c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 56665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(left_operand->representation().Equals( 56675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch right_operand->representation())); 56685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(!left_operand->representation().IsTagged()); 56695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 5670c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Token::Value op = (id == kMathMin) ? Token::LT : Token::GT; 56715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 56725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HCompareIDAndBranch* compare = 56735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HCompareIDAndBranch(left_operand, right_operand, op); 56745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch compare->SetInputRepresentation(left_operand->representation()); 5675c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 5676c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HBasicBlock* return_left = graph()->CreateBasicBlock(); 5677c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HBasicBlock* return_right = graph()->CreateBasicBlock(); 5678c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 5679c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch compare->SetSuccessorAt(0, return_left); 5680c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch compare->SetSuccessorAt(1, return_right); 5681c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch current_block()->Finish(compare); 5682c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 5683c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch set_current_block(return_left); 5684c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Push(left); 5685c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch set_current_block(return_right); 5686c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Push(right); 5687c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 5688c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HBasicBlock* join = CreateJoin(return_left, return_right, expr->id()); 5689c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch set_current_block(join); 5690c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ast_context()->ReturnValue(Pop()); 5691c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return true; 5692c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 5693c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch break; 5694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 5695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Not yet supported for inlining. 5696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 5697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 5699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryCallApply(Call* expr) { 5703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* callee = expr->expression(); 5704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = callee->AsProperty(); 5705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(prop != NULL); 5706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 570742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch if (!expr->IsMonomorphic() || expr->check_type() != RECEIVER_MAP_CHECK) { 570842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch return false; 570942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch } 571042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch Handle<Map> function_map = expr->GetReceiverTypes()->first(); 571142effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch if (function_map->instance_type() != JS_FUNCTION_TYPE || 571242effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch !expr->target()->shared()->HasBuiltinFunctionId() || 571342effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch expr->target()->shared()->builtin_function_id() != kFunctionApply) { 571442effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch return false; 571542effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch } 5716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 571742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch if (info()->scope()->arguments() == NULL) return false; 5718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 5720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (args->length() != 2) return false; 5721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 5723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 5724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* arg_two_value = environment()->Lookup(arg_two->var()); 5725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 5726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Found pattern f.apply(receiver, arguments). 5728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(prop->obj()); 5729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return true; 5730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* function = Top(); 5731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddCheckConstantFunction(expr, function, function_map, true); 5732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Drop(1); 5733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(args->at(0)); 5735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return true; 5736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver = Pop(); 57375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 57385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (function_state()->outer() == NULL) { 57395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 57405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* length = 57415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddInstruction(new(zone()) HArgumentsLength(elements)); 57425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* wrapped_receiver = 57435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddInstruction(new(zone()) HWrapReceiver(receiver, function)); 57445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* result = 57455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HApplyArguments(function, 57465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch wrapped_receiver, 57475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch length, 57485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch elements); 57495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch result->set_position(expr->position()); 57505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ast_context()->ReturnInstruction(result, expr->id()); 57515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return true; 57525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else { 57535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // We are inside inlined function and we know exactly what is inside 57545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // arguments object. 57555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* context = environment()->LookupContext(); 57565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 57575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* wrapped_receiver = 57585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddInstruction(new(zone()) HWrapReceiver(receiver, function)); 57595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PushAndAdd(new(zone()) HPushArgument(wrapped_receiver)); 57605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 57615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HEnvironment* arguments_env = environment()->arguments_environment(); 57625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 57635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int parameter_count = arguments_env->parameter_count(); 57645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (int i = 1; i < arguments_env->parameter_count(); i++) { 57655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PushAndAdd(new(zone()) HPushArgument(arguments_env->Lookup(i))); 57665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 57675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 57685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInvokeFunction* call = new(zone()) HInvokeFunction( 57695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch context, 57705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch function, 57715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch parameter_count); 57725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Drop(parameter_count); 57735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch call->set_position(expr->position()); 57745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ast_context()->ReturnInstruction(call, expr->id()); 57755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return true; 57765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 5777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCall(Call* expr) { 5781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 5782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 5783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 5784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* callee = expr->expression(); 5785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length() + 1; // Plus receiver. 5786e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HInstruction* call = NULL; 5787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = callee->AsProperty(); 5789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop != NULL) { 5790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!prop->key()->IsPropertyName()) { 5791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed function call. 57923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_ALIVE(VisitArgument(prop->obj())); 5793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 5795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push receiver and key like the non-optimized code generator expects it. 5796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 5797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver = Pop(); 5798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(key); 5799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(receiver); 5800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 58013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 58043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch call = new(zone()) HCallKeyed(context, key, argument_count); 5805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 58063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Drop(argument_count + 1); // 1 is the key. 58073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 5808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named function call. 5811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch expr->RecordTypeFeedback(oracle(), CALL_AS_METHOD); 5812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (TryCallApply(expr)) return; 5814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 5816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 5817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 5819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 582069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch SmallMapList* types = expr->GetReceiverTypes(); 5821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 58221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* receiver = 58231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block environment()->ExpressionStackAt(expr->arguments()->length()); 58241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (expr->IsMonomorphic()) { 582569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch Handle<Map> receiver_map = (types == NULL || types->is_empty()) 582669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ? Handle<Map>::null() 582769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch : types->first(); 58285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (TryInlineBuiltinMethodCall(expr, 58295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch receiver, 58305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch receiver_map, 58315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->check_type())) { 58325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (FLAG_trace_inlining) { 58335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintF("Inlining builtin "); 58345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->target()->ShortPrint(); 58355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintF("\n"); 58365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 5837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 5838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5840592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || 58411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block expr->check_type() != RECEIVER_MAP_CHECK) { 58421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // When the target has a custom call IC generator, use the IC, 584344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // because it is likely to generate better code. Also use the IC 584444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // when a primitive receiver check is required. 5845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 58468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall( 58478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallNamed(context, name, argument_count)); 58481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 58491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddCheckConstantFunction(expr, receiver, receiver_map, true); 58501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 58515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (TryInlineCall(expr)) return; 5852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch call = PreProcessCall( 5853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch new(zone()) HCallConstantFunction(expr->target(), 5854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch argument_count)); 58551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 5856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (types != NULL && types->length() > 1) { 5857b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 5858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandlePolymorphicCallNamed(expr, receiver, types, name); 5859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 5860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 58638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall( 58648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallNamed(context, name, argument_count)); 5865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5868592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch expr->RecordTypeFeedback(oracle(), CALL_AS_FUNCTION); 5869589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 5870589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); 5871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 58725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (proxy != NULL && proxy->var()->is_possibly_eval()) { 58735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return Bailout("possible direct call to eval"); 58745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 58755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 5876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (global_call) { 5877589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 5878e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bool known_global_function = false; 5879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If there is a global property cell for the name at compile time and 5880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // access check is not enabled we assume that the function will not change 5881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // and generate optimized code for calling the function. 5882592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch LookupResult lookup(isolate()); 58838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 58848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (type == kUseCell && 5885e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !info()->global_object()->IsAccessCheckNeeded()) { 5886e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<GlobalObject> global(info()->global_object()); 58878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch known_global_function = expr->ComputeGlobalTarget(global, &lookup); 5888e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 5889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (known_global_function) { 5890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push the global object instead of the global receiver because 5891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // code generated by the full code generator expects it. 5892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 58938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 58941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PushAndAdd(global_object); 5895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 5896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 5898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* function = Pop(); 58998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 5900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Replace the global object with the global receiver. 59028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalReceiver* global_receiver = 59038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HGlobalReceiver(global_object); 5904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Index of the receiver from the top of the expression stack. 5905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const int receiver_index = argument_count - 1; 5906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(global_receiver); 5907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(environment()->ExpressionStackAt(receiver_index)-> 5908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch IsGlobalObject()); 5909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(receiver_index, global_receiver); 5910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 59115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (TryInlineBuiltinFunctionCall(expr, false)) { // Nothing to drop. 59125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (FLAG_trace_inlining) { 59135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintF("Inlining builtin "); 59145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->target()->ShortPrint(); 59155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintF("\n"); 59165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 59175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return; 59185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 59195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (TryInlineCall(expr)) return; 59208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), 5921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch argument_count)); 5922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 59243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HGlobalObject* receiver = new(zone()) HGlobalObject(context); 59253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(receiver); 59263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PushAndAdd(new(zone()) HPushArgument(receiver)); 59273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 59293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch call = new(zone()) HCallGlobal(context, var->name(), argument_count); 59303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Drop(argument_count); 5931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5933592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else if (expr->IsMonomorphic()) { 5934592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // The function is on the stack in the unoptimized code during 5935592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // evaluation of the arguments. 5936592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 5937592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* function = Top(); 5938592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* context = environment()->LookupContext(); 5939592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HGlobalObject* global = new(zone()) HGlobalObject(context); 5940592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global); 5941592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch AddInstruction(global); 5942592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch PushAndAdd(receiver); 5943592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 5944592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 59455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 59465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (TryInlineBuiltinFunctionCall(expr, true)) { // Drop the function. 59475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (FLAG_trace_inlining) { 59485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintF("Inlining builtin "); 59495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->target()->ShortPrint(); 59505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintF("\n"); 59515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 59525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return; 59535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 59545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 59555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (TryInlineCall(expr, true)) { // Drop function from environment. 5956592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return; 5957592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 5958592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch call = PreProcessCall(new(zone()) HInvokeFunction(context, 5959592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch function, 5960592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch argument_count)); 5961592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Drop(1); // The function. 5962592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 5963592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 5964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5965592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 5966592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* function = Top(); 5967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 59688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 59693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HGlobalReceiver* receiver = new(zone()) HGlobalReceiver(global_object); 59701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(global_object); 59713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(receiver); 59723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PushAndAdd(new(zone()) HPushArgument(receiver)); 59733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 5974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5975592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch call = new(zone()) HCallFunction(context, function, argument_count); 59763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Drop(argument_count + 1); 5977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 59813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 5982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 59855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch// Checks whether allocation using the given constructor can be inlined. 59865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochstatic bool IsAllocationInlineable(Handle<JSFunction> constructor) { 59875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return constructor->has_initial_map() && 59885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch constructor->initial_map()->instance_type() == JS_OBJECT_TYPE; 59895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 59905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 59915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 5992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallNew(CallNew* expr) { 5993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 5994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 5995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 59965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->RecordTypeFeedback(oracle()); 59975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int argument_count = expr->arguments()->length() + 1; // Plus constructor. 5998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 59991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 60005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (FLAG_inline_construct && 60015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch expr->IsMonomorphic() && 60025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch IsAllocationInlineable(expr->target())) { 60035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // The constructor function is on the stack in the unoptimized code 60045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // during evaluation of the arguments. 60055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 60065d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* function = Top(); 60075d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 60085d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<JSFunction> constructor = expr->target(); 60095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* check = AddInstruction( 60105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HCheckFunction(function, constructor)); 60115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 60125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Force completion of inobject slack tracking before generating 60135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // allocation code to finalize instance size. 60145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (constructor->shared()->IsInobjectSlackTrackingInProgress()) { 60155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch constructor->shared()->CompleteInobjectSlackTracking(); 60165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 60175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 60185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Replace the constructor function with a newly allocated receiver. 60195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* receiver = new(zone()) HAllocateObject(context, constructor); 60205d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Index of the receiver from the top of the expression stack. 60215d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch const int receiver_index = argument_count - 1; 60225d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddInstruction(receiver); 60235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(environment()->ExpressionStackAt(receiver_index) == function); 60245d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->SetExpressionStackAt(receiver_index, receiver); 60255d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 60265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (TryInlineConstruct(expr, receiver)) return; 60275d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 60285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // TODO(mstarzinger): For now we remove the previous HAllocateObject and 60295d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // add HPushArgument for the arguments in case inlining failed. What we 60305d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // actually should do is emit HInvokeFunction on the constructor instead 60315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // of using HCallNew as a fallback. 60325d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch receiver->DeleteAndReplaceWith(NULL); 60335d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch check->DeleteAndReplaceWith(NULL); 60345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch environment()->SetExpressionStackAt(receiver_index, function); 60355d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* call = PreProcessCall( 60365d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HCallNew(context, function, argument_count)); 60375d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch call->set_position(expr->position()); 60385d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 60395d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else { 60405d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // The constructor function is both an operand to the instruction and an 60415d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // argument to the construct call. 60425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* constructor = NULL; 60435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_ALIVE(constructor = VisitArgument(expr->expression())); 60445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 60455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* call = 60465d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HCallNew(context, constructor, argument_count); 60475d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Drop(argument_count); 60485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch call->set_position(expr->position()); 60495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 60505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 6051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for generating inlined runtime functions. 6055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Lookup table for generators for runtime calls that are generated inline. 6057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Elements of the table are member pointers to functions of HGraphBuilder. 6058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 6059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &HGraphBuilder::Generate##Name, 6060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst HGraphBuilder::InlineFunctionGenerator 6062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder::kInlineFunctionGenerators[] = { 6063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 6064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 6065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 6066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef INLINE_FUNCTION_GENERATOR_ADDRESS 6067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 6070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 6073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->is_jsruntime()) { 6074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("call to a JavaScript runtime function"); 6075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 607744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Runtime::Function* function = expr->function(); 6078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(function != NULL); 6079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (function->intrinsic_type == Runtime::INLINE) { 6080e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(expr->name()->length() > 0); 6081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(expr->name()->Get(0) == '_'); 6082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Call to an inline function. 6083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int lookup_index = static_cast<int>(function->function_id) - 6084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(Runtime::kFirstInlineFunction); 6085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(lookup_index >= 0); 6086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(static_cast<size_t>(lookup_index) < 6087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ARRAY_SIZE(kInlineFunctionGenerators)); 6088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 6089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Call the inline code generator using the pointer-to-member. 6091e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (this->*generator)(expr); 6092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(function->intrinsic_type == Runtime::RUNTIME); 6094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 6095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 60963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 6097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<String> name = expr->name(); 6098e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int argument_count = expr->arguments()->length(); 60998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallRuntime* call = 61003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HCallRuntime(context, name, function, argument_count); 6101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(RelocInfo::kNoPosition); 6102e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(argument_count); 61033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(call, expr->id()); 6104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 6109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 6112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (expr->op()) { 6113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::DELETE: return VisitDelete(expr); 6114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::VOID: return VisitVoid(expr); 6115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::TYPEOF: return VisitTypeof(expr); 6116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::ADD: return VisitAdd(expr); 6117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::SUB: return VisitSub(expr); 6118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::BIT_NOT: return VisitBitNot(expr); 6119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case Token::NOT: return VisitNot(expr); 6120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch default: UNREACHABLE(); 6121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitDelete(UnaryOperation* expr) { 6125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Property* prop = expr->expression()->AsProperty(); 6126589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->expression()->AsVariableProxy(); 6127589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (prop != NULL) { 612869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 612969a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 613069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HValue* key = Pop(); 613169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HValue* obj = Pop(); 613269a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HValue* context = environment()->LookupContext(); 613369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch HDeleteProperty* instr = new(zone()) HDeleteProperty(context, obj, key); 613469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6135589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (proxy != NULL) { 6136589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 6137589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsUnallocated()) { 6138589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Bailout("delete with global variable"); 6139589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (var->IsStackAllocated() || var->IsContextSlot()) { 6140589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Result of deleting non-global variables is false. 'this' is not 6141589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // really a variable, though we implement it as one. The 6142589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // subexpression does not have side effects. 6143589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* value = var->is_this() 6144589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ? graph()->GetConstantTrue() 6145589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch : graph()->GetConstantFalse(); 6146589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ast_context()->ReturnValue(value); 6147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 6148589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Bailout("delete with non-global variable"); 6149589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 6150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6151589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Result of deleting non-property, non-variable reference is true. 6152589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Evaluate the subexpression for side effects. 6153589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch CHECK_ALIVE(VisitForEffect(expr->expression())); 6154589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return ast_context()->ReturnValue(graph()->GetConstantTrue()); 6155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 615844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitVoid(UnaryOperation* expr) { 6160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForEffect(expr->expression())); 61613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 6162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitTypeof(UnaryOperation* expr) { 6166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForTypeOf(expr->expression())); 6167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = Pop(); 61683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 61693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = new(zone()) HTypeof(context, value); 61703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitAdd(UnaryOperation* expr) { 6175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 6176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = Pop(); 61773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 61783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = 61793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HMul(context, value, graph_->GetConstant1()); 61803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitSub(UnaryOperation* expr) { 6185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 6186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = Pop(); 61873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 61883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = 61893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HMul(context, value, graph_->GetConstantMinus1()); 6190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TypeInfo info = oracle()->UnaryType(expr); 61913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (info.IsUninitialized()) { 61923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HSoftDeoptimize); 61933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->MarkAsDeoptimizing(); 61943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch info = TypeInfo::Unknown(); 61953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation rep = ToRepresentation(info); 6197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceRepresentation(expr->op(), info, instr, rep); 6198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->AssumeRepresentation(rep); 61993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitBitNot(UnaryOperation* expr) { 6204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 6205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = Pop(); 62063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch TypeInfo info = oracle()->UnaryType(expr); 62073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (info.IsUninitialized()) { 62083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HSoftDeoptimize); 62093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->MarkAsDeoptimizing(); 62103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HInstruction* instr = new(zone()) HBitNot(value); 62123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitNot(UnaryOperation* expr) { 6217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (ast_context()->IsTest()) { 6218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TestContext* context = TestContext::cast(ast_context()); 6219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForControl(expr->expression(), 6220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context->if_false(), 6221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context->if_true()); 6222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return; 6223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (ast_context()->IsEffect()) { 6226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch VisitForEffect(expr->expression()); 6227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return; 6228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(ast_context()->IsValue()); 6231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* materialize_false = graph()->CreateBasicBlock(); 6232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* materialize_true = graph()->CreateBasicBlock(); 6233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->expression(), 6234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch materialize_false, 6235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch materialize_true)); 6236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (materialize_false->HasPredecessor()) { 6238592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch materialize_false->SetJoinId(expr->MaterializeFalseId()); 6239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(materialize_false); 6240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Push(graph()->GetConstantFalse()); 624144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 6242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch materialize_false = NULL; 6243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (materialize_true->HasPredecessor()) { 6246592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch materialize_true->SetJoinId(expr->MaterializeTrueId()); 6247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(materialize_true); 6248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Push(graph()->GetConstantTrue()); 6249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch materialize_true = NULL; 6251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* join = 6254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CreateJoin(materialize_false, materialize_true, expr->id()); 6255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(join); 62563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (join != NULL) return ast_context()->ReturnValue(Pop()); 6257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHInstruction* HGraphBuilder::BuildIncrement(bool returns_original_input, 6261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CountOperation* expr) { 6262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The input to the count operation is on top of the expression stack. 6263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TypeInfo info = oracle()->IncrementType(expr); 6264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation rep = ToRepresentation(info); 6265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (rep.IsTagged()) { 6266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rep = Representation::Integer32(); 6267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (returns_original_input) { 6270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We need an explicit HValue representing ToNumber(input). The 6271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // actual HChange instruction we need is (sometimes) added in a later 6272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // phase, so it is not available now to be used as an input to HAdd and 6273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // as the return value. 6274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HInstruction* number_input = new(zone()) HForceRepresentation(Pop(), rep); 6275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(number_input); 6276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Push(number_input); 6277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The addition has no side effects, so we do not need 6280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // to simulate the expression stack after this instruction. 6281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Any later failures deopt to the load of the input or earlier. 6282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HConstant* delta = (expr->op() == Token::INC) 6283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? graph_->GetConstant1() 6284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : graph_->GetConstantMinus1(); 62853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 62863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = new(zone()) HAdd(context, Top(), delta); 6287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceRepresentation(expr->op(), info, instr, rep); 6288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->AssumeRepresentation(rep); 6289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(instr); 6290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 6291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCountOperation(CountOperation* expr) { 6295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 62988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Expression* target = expr->expression(); 6299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = target->AsVariableProxy(); 6300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = target->AsProperty(); 6301589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy == NULL && prop == NULL) { 6302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("invalid lhs in count operation"); 6303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Match the full code generator stack by simulating an extra stack 6306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // element for postfix operations in a non-effect context. The return 6307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // value is ToNumber(input). 6308257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool returns_original_input = 6309257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch expr->is_postfix() && !ast_context()->IsEffect(); 6310257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* input = NULL; // ToNumber(original_input). 6311257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* after = NULL; // The result after incrementing or decrementing. 6312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6313589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (proxy != NULL) { 6314589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 6315592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (var->mode() == CONST) { 63163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return Bailout("unsupported count operation with const"); 63173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument of the count operation is a variable, not a property. 6319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(prop == NULL); 6320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(target)); 6321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch after = BuildIncrement(returns_original_input, expr); 6323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch input = returns_original_input ? Top() : Pop(); 6324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(after); 6325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6326589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 6327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: 6328589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HandleGlobalVariableAssignment(var, 6329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch after, 6330589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch expr->position(), 6331589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch expr->AssignmentId()); 6332589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 6333589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 6334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 6335589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 6336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Bind(var, after); 6337589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 6338589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 6339589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: { 6340589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Bail out if we try to mutate a parameter value in a function 6341589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // using the arguments object. We do not (yet) correctly handle the 6342589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // arguments property of the function. 6343589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (info()->scope()->arguments() != NULL) { 6344589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // Parameters will rewrite to context slots. We have no direct 6345589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // way to detect that the variable is a parameter so we use a 6346589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch // linear search of the parameter list. 6347589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch int count = info()->scope()->num_parameters(); 6348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch for (int i = 0; i < count; ++i) { 6349589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var == info()->scope()->parameter(i)) { 6350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Bailout("assignment to parameter in arguments object"); 6351589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 63523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 63533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6354589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 6355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = BuildContextChainWalk(var); 6356c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HStoreContextSlot::Mode mode = 6357c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch (var->mode() == LET || var->mode() == CONST_HARMONY) 6358c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck; 6359589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HStoreContextSlot* instr = 6360c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch new(zone()) HStoreContextSlot(context, var->index(), mode, after); 6361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddInstruction(instr); 6362592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (instr->HasObservableSideEffects()) { 6363592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch AddSimulate(expr->AssignmentId()); 6364592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 6365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 63663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 63673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: 6369589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Bailout("lookup variable in count operation"); 6370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument of the count operation is a property. 6374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(prop != NULL); 6375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prop->RecordTypeFeedback(oracle()); 6376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->key()->IsPropertyName()) { 6378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named property. 6379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (returns_original_input) Push(graph_->GetConstantUndefined()); 6380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 6382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Top(); 6383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* load = NULL; 6385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->IsMonomorphic()) { 6386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 6387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = prop->GetReceiverTypes()->first(); 6388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamed(obj, prop, map, name); 6389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamedGeneric(obj, prop); 6391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 6393592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (load->HasObservableSideEffects()) AddSimulate(expr->CountId()); 6394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch after = BuildIncrement(returns_original_input, expr); 6396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch input = Pop(); 6397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* store = BuildStoreNamed(obj, after, prop); 6399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 6400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Overwrite the receiver in the bailout environment with the result 6402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the operation, and the placeholder with the original value if 6403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // necessary. 6404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(0, after); 6405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (returns_original_input) environment()->SetExpressionStackAt(1, input); 6406592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (store->HasObservableSideEffects()) AddSimulate(expr->AssignmentId()); 6407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed property. 6410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (returns_original_input) Push(graph_->GetConstantUndefined()); 6411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 6413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 6414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = environment()->ExpressionStackAt(1); 6415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = environment()->ExpressionStackAt(0); 6416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 64173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool has_side_effects = false; 64183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* load = HandleKeyedElementAccess( 64193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch obj, key, NULL, prop, expr->CountId(), RelocInfo::kNoPosition, 64203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch false, // is_store 64213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &has_side_effects); 64223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Push(load); 64233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (has_side_effects) AddSimulate(expr->CountId()); 6424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch after = BuildIncrement(returns_original_input, expr); 6426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch input = Pop(); 6427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 64288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->RecordTypeFeedback(oracle()); 64293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HandleKeyedElementAccess(obj, key, after, expr, expr->AssignmentId(), 64303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch RelocInfo::kNoPosition, 64313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch true, // is_store 64323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch &has_side_effects); 6433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop the key from the bailout environment. Overwrite the receiver 6435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // with the result of the operation, and the placeholder with the 6436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // original value if necessary. 6437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(1); 6438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(0, after); 6439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (returns_original_input) environment()->SetExpressionStackAt(1, input); 64403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(has_side_effects); // Stores always have side effects. 64413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddSimulate(expr->AssignmentId()); 6442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Drop(returns_original_input ? 2 : 1); 64463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(expr->is_postfix() ? input : after); 6447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 64503fb3ca8c7ca439d408449a395897395c0faae8d1Ben MurdochHStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* context, 64513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* string, 64521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* index) { 64538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(string)); 6454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch AddInstruction(HCheckInstanceType::NewIsString(string)); 64558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStringLength* length = new(zone()) HStringLength(string); 64561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(length); 64577d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch HInstruction* checked_index = 64587d3e7fc4b65010eabe860313ee0c64f50843f6e3Ben Murdoch AddInstruction(new(zone()) HBoundsCheck(index, length)); 64593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return new(zone()) HStringCharCodeAt(context, string, checked_index); 64601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 64611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 64621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 6463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 6464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left, 6465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right) { 64663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 6467053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block TypeInfo info = oracle()->BinaryType(expr); 64683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (info.IsUninitialized()) { 64693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HSoftDeoptimize); 64703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->MarkAsDeoptimizing(); 64713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch info = TypeInfo::Unknown(); 64723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 64733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstruction* instr = NULL; 64743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (expr->op()) { 64753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::ADD: 64763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (info.IsString()) { 64773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(left)); 64783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(HCheckInstanceType::NewIsString(left)); 64793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(right)); 64803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(HCheckInstanceType::NewIsString(right)); 64813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch instr = new(zone()) HStringAdd(context, left, right); 64823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 6483592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr = HAdd::NewHAdd(zone(), context, left, right); 64843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 64853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 64863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::SUB: 6487592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr = HSub::NewHSub(zone(), context, left, right); 64883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 64893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::MUL: 6490592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr = HMul::NewHMul(zone(), context, left, right); 64913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 64923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::MOD: 6493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr = HMod::NewHMod(zone(), context, left, right); 64943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 64953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::DIV: 6496592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr = HDiv::NewHDiv(zone(), context, left, right); 64973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 64983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::BIT_XOR: 64993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::BIT_AND: 65003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::BIT_OR: 6501592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr = HBitwise::NewHBitwise(zone(), expr->op(), context, left, right); 65023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::SAR: 6504592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr = HSar::NewHSar(zone(), context, left, right); 65053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::SHR: 6507592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr = HShr::NewHShr(zone(), context, left, right); 65083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::SHL: 6510592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr = HShl::NewHShl(zone(), context, left, right); 65113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch break; 65123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch default: 65133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch UNREACHABLE(); 65143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 65153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If we hit an uninitialized binary op stub we will get type info 6517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // for a smi operation. If one of the operands is a constant string 6518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // do not generate code assuming it is a smi operation. 6519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsSmi() && 6520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || 6521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { 6522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 6523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 65241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Representation rep = ToRepresentation(info); 65251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We only generate either int32 or generic tagged bitwise operations. 65261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) { 65271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block rep = Representation::Integer32(); 65281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 6529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TraceRepresentation(expr->op(), info, instr, rep); 6530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->AssumeRepresentation(rep); 6531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 6532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check for the form (%_ClassOf(foo) === 'BarClass'). 6536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsClassOfTest(CompareOperation* expr) { 6537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->op() != Token::EQ_STRICT) return false; 6538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CallRuntime* call = expr->left()->AsCallRuntime(); 6539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (call == NULL) return false; 6540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* literal = expr->right()->AsLiteral(); 6541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (literal == NULL) return false; 6542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!literal->handle()->IsString()) return false; 6543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 6544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(call->arguments()->length() == 1); 6545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 6546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 6550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 6553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (expr->op()) { 65543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::COMMA: 65553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return VisitComma(expr); 65563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::OR: 65573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch case Token::AND: 65583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return VisitLogicalExpression(expr); 65593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch default: 65603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return VisitArithmeticExpression(expr); 6561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::VisitComma(BinaryOperation* expr) { 6566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForEffect(expr->left())); 6567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Visit the right subexpression in the same AST context as the entire 6568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // expression. 6569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Visit(expr->right()); 6570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 6572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 65733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { 65743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_logical_and = expr->op() == Token::AND; 6575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (ast_context()->IsTest()) { 6576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TestContext* context = TestContext::cast(ast_context()); 6577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Translate left subexpression. 6578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* eval_right = graph()->CreateBasicBlock(); 6579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_logical_and) { 6580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), 6581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch eval_right, 6582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context->if_false())); 6583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), 6585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch context->if_true(), 6586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch eval_right)); 6587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Translate right subexpression by visiting it in the same AST 6590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // context as the entire expression. 6591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (eval_right->HasPredecessor()) { 6592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch eval_right->SetJoinId(expr->RightId()); 6593e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(eval_right); 6594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Visit(expr->right()); 6595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6596e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 6597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (ast_context()->IsValue()) { 6598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->left())); 6599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We need an extra block to maintain edge-split form. 6602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* empty_block = graph()->CreateBasicBlock(); 6603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* eval_right = graph()->CreateBasicBlock(); 660469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch unsigned test_id = expr->left()->test_id(); 660569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id)); 66063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HBranch* test = is_logical_and 660769a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch ? new(zone()) HBranch(Top(), eval_right, empty_block, expected) 660869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch : new(zone()) HBranch(Top(), empty_block, eval_right, expected); 6609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current_block()->Finish(test); 6610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(eval_right); 6612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Drop(1); // Value of the left subexpression. 6613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForValue(expr->right())); 6614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* join_block = 6616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CreateJoin(empty_block, current_block(), expr->id()); 6617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(join_block); 66183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(Pop()); 6619e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 6620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(ast_context()->IsEffect()); 6622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // In an effect context, we don't need the value of the left subexpression, 6623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // only its control flow and side effects. We need an extra block to 6624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // maintain edge-split form. 6625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* empty_block = graph()->CreateBasicBlock(); 6626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* right_block = graph()->CreateBasicBlock(); 6627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_logical_and) { 6628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block)); 6629e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 6630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block)); 6631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TODO(kmillikin): Find a way to fix this. It's ugly that there are 6634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // actually two empty blocks (one here and one inserted by 6635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TestContext::BuildBranch, and that they both have an HSimulate though the 6636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // second one is not a merge node, and that we really have no good AST ID to 6637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // put on that first HSimulate. 6638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (empty_block->HasPredecessor()) { 6640053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block empty_block->SetJoinId(expr->id()); 6641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch empty_block = NULL; 6643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 6644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (right_block->HasPredecessor()) { 6646053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block right_block->SetJoinId(expr->RightId()); 6647053d10c438f14580aaf4ab1b2aad93a5a4fe8b82Steve Block set_current_block(right_block); 6648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_BAILOUT(VisitForEffect(expr->right())); 6649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch right_block = current_block(); 6650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch right_block = NULL; 6652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HBasicBlock* join_block = 6655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CreateJoin(empty_block, right_block, expr->id()); 6656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch set_current_block(join_block); 6657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We did not materialize any value in the predecessor environments, 6658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // so there is no need to handle it here. 6659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 66633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid HGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) { 6664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->left())); 6665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->right())); 6666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* right = Pop(); 6667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* left = Pop(); 6668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HInstruction* instr = BuildBinaryOperation(expr, left, right); 6669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch instr->set_position(expr->position()); 66703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(instr, expr->id()); 6671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 6672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid HGraphBuilder::TraceRepresentation(Token::Value op, 6675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch TypeInfo info, 6676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value, 6677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Representation rep) { 6678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!FLAG_trace_representation) return; 6679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // TODO(svenpanne) Under which circumstances are we actually not flexible? 6680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // At first glance, this looks a bit weird... 6681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool flexible = value->CheckFlag(HValue::kFlexibleRepresentation); 6682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintF("Operation %s has type info %s, %schange representation assumption " 6683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "for %s (ID %d) from %s to %s\n", 6684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Token::Name(op), 6685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch info.ToString(), 6686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch flexible ? "" : " DO NOT ", 6687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value->Mnemonic(), 6688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch graph_->GetMaximumValueID(), 6689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value->representation().Mnemonic(), 6690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch rep.Mnemonic()); 6691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HGraphBuilder::ToRepresentation(TypeInfo info) { 6695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsSmi()) return Representation::Integer32(); 6696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsInteger32()) return Representation::Integer32(); 6697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsDouble()) return Representation::Double(); 6698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsNumber()) return Representation::Double(); 6699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::Tagged(); 6700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6703592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr, 6704592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HTypeof* typeof_expr, 67053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<String> check) { 6706592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Note: The HTypeof itself is removed during canonicalization, if possible. 6707592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* value = typeof_expr->value(); 6708592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HTypeofIsAndBranch* instr = new(zone()) HTypeofIsAndBranch(value, check); 6709592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr->set_position(expr->position()); 6710592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return ast_context()->ReturnControl(instr, expr->id()); 67113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 67123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 67133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6714592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic bool MatchLiteralCompareNil(HValue* left, 6715592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Token::Value op, 6716592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* right, 6717592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> nil, 6718592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue** expr) { 6719592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (left->IsConstant() && 6720592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HConstant::cast(left)->handle().is_identical_to(nil) && 6721592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Token::IsEqualityOp(op)) { 6722592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch *expr = right; 6723592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return true; 6724592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 6725592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return false; 6726592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 6727592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 6728592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 6729592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic bool MatchLiteralCompareTypeof(HValue* left, 6730592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Token::Value op, 6731592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* right, 6732592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HTypeof** typeof_expr, 6733592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String>* check) { 6734592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (left->IsTypeof() && 6735592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Token::IsEqualityOp(op) && 6736592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch right->IsConstant() && 6737592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HConstant::cast(right)->HasStringValue()) { 6738592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch *typeof_expr = HTypeof::cast(left); 6739592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch *check = Handle<String>::cast(HConstant::cast(right)->handle()); 6740592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return true; 6741592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 6742592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return false; 6743592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 6744592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 6745592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 6746592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic bool IsLiteralCompareTypeof(HValue* left, 6747592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Token::Value op, 6748592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* right, 6749592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HTypeof** typeof_expr, 6750592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String>* check) { 6751592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return MatchLiteralCompareTypeof(left, op, right, typeof_expr, check) || 6752592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MatchLiteralCompareTypeof(right, op, left, typeof_expr, check); 6753592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 6754592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 6755592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 6756592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochstatic bool IsLiteralCompareNil(HValue* left, 6757592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Token::Value op, 6758592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* right, 6759592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<Object> nil, 6760592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue** expr) { 6761592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return MatchLiteralCompareNil(left, op, right, nil, expr) || 6762592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch MatchLiteralCompareNil(right, op, left, nil, expr); 67633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 67643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 67653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6766c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdochstatic bool IsLiteralCompareBool(HValue* left, 6767c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Token::Value op, 6768c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HValue* right) { 6769c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return op == Token::EQ_STRICT && 6770c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ((left->IsConstant() && HConstant::cast(left)->handle()->IsBoolean()) || 6771c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch (right->IsConstant() && HConstant::cast(right)->handle()->IsBoolean())); 6772c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch} 6773c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 6774c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 6775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 6776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 6779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (IsClassOfTest(expr)) { 6780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CallRuntime* call = expr->left()->AsCallRuntime(); 67813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ASSERT(call->arguments()->length() == 1); 6782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 6783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 6784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* literal = expr->right()->AsLiteral(); 6785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> rhs = Handle<String>::cast(literal->handle()); 67863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HClassOfTestAndBranch* instr = 67873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HClassOfTestAndBranch(value, rhs); 6788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 67893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(instr, expr->id()); 67903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 67913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 67923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch TypeInfo type_info = oracle()->CompareType(expr); 67933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check if this expression was ever executed according to type feedback. 6794592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Note that for the special typeof/null/undefined cases we get unknown here. 67953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (type_info.IsUninitialized()) { 67963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HSoftDeoptimize); 67973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch current_block()->MarkAsDeoptimizing(); 67983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch type_info = TypeInfo::Unknown(); 67993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 68003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 6801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->left())); 6802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(expr->right())); 6803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 68043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 6805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 6806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 6807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Value op = expr->op(); 6808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6809592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HTypeof* typeof_expr = NULL; 6810592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> check; 6811592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (IsLiteralCompareTypeof(left, op, right, &typeof_expr, &check)) { 6812592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return HandleLiteralCompareTypeof(expr, typeof_expr, check); 6813592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 6814592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* sub_expr = NULL; 6815592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Factory* f = graph()->isolate()->factory(); 6816592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (IsLiteralCompareNil(left, op, right, f->undefined_value(), &sub_expr)) { 6817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue); 6818592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 6819592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (IsLiteralCompareNil(left, op, right, f->null_value(), &sub_expr)) { 6820592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return HandleLiteralCompareNil(expr, sub_expr, kNullValue); 6821592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 6822c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (IsLiteralCompareBool(left, op, right)) { 6823c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HCompareObjectEqAndBranch* result = 6824c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch new(zone()) HCompareObjectEqAndBranch(left, right); 6825c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch result->set_position(expr->position()); 6826c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return ast_context()->ReturnControl(result, expr->id()); 6827c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 6828592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 6829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::INSTANCEOF) { 6830086aeeaae12517475c22695a200be45495516549Ben Murdoch // Check to see if the rhs of the instanceof is a global function not 6831086aeeaae12517475c22695a200be45495516549Ben Murdoch // residing in new space. If it is we assume that the function will stay the 6832086aeeaae12517475c22695a200be45495516549Ben Murdoch // same. 6833086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<JSFunction> target = Handle<JSFunction>::null(); 6834589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch VariableProxy* proxy = expr->right()->AsVariableProxy(); 6835589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated(); 6836086aeeaae12517475c22695a200be45495516549Ben Murdoch if (global_function && 6837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch info()->has_global_object() && 6838e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !info()->global_object()->IsAccessCheckNeeded()) { 6839589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Handle<String> name = proxy->name(); 6840e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<GlobalObject> global(info()->global_object()); 6841592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch LookupResult lookup(isolate()); 6842086aeeaae12517475c22695a200be45495516549Ben Murdoch global->Lookup(*name, &lookup); 6843c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (lookup.IsFound() && 6844086aeeaae12517475c22695a200be45495516549Ben Murdoch lookup.type() == NORMAL && 6845086aeeaae12517475c22695a200be45495516549Ben Murdoch lookup.GetValue()->IsJSFunction()) { 6846086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); 6847086aeeaae12517475c22695a200be45495516549Ben Murdoch // If the function is in new space we assume it's more likely to 6848086aeeaae12517475c22695a200be45495516549Ben Murdoch // change and thus prefer the general IC code. 684944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!isolate()->heap()->InNewSpace(*candidate)) { 6850086aeeaae12517475c22695a200be45495516549Ben Murdoch target = candidate; 6851086aeeaae12517475c22695a200be45495516549Ben Murdoch } 6852086aeeaae12517475c22695a200be45495516549Ben Murdoch } 6853086aeeaae12517475c22695a200be45495516549Ben Murdoch } 6854086aeeaae12517475c22695a200be45495516549Ben Murdoch 6855086aeeaae12517475c22695a200be45495516549Ben Murdoch // If the target is not null we have found a known global function that is 6856086aeeaae12517475c22695a200be45495516549Ben Murdoch // assumed to stay the same for this instanceof. 6857086aeeaae12517475c22695a200be45495516549Ben Murdoch if (target.is_null()) { 68583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstanceOf* result = new(zone()) HInstanceOf(context, left, right); 68593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 68603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, expr->id()); 6861086aeeaae12517475c22695a200be45495516549Ben Murdoch } else { 68628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckFunction(right, target)); 68633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HInstanceOfKnownGlobal* result = 68643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HInstanceOfKnownGlobal(context, left, target); 68653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 68663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, expr->id()); 6867086aeeaae12517475c22695a200be45495516549Ben Murdoch } 6868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::IN) { 68693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HIn* result = new(zone()) HIn(context, left, right); 68703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 68713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, expr->id()); 6872e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (type_info.IsNonPrimitive()) { 6873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (op) { 6874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ: 6875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ_STRICT: { 6876c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Can we get away with map check and not instance type check? 6877c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Handle<Map> map = oracle()->GetCompareMap(expr); 6878c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (!map.is_null()) { 6879c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(left)); 6880c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckMap(left, map, NULL, 6881c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ALLOW_ELEMENT_TRANSITION_MAPS)); 6882c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(right)); 6883c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckMap(right, map, NULL, 6884c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ALLOW_ELEMENT_TRANSITION_MAPS)); 6885c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HCompareObjectEqAndBranch* result = 6886c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch new(zone()) HCompareObjectEqAndBranch(left, right); 6887c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch result->set_position(expr->position()); 6888c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return ast_context()->ReturnControl(result, expr->id()); 6889c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } else { 6890c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(left)); 6891c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(HCheckInstanceType::NewIsSpecObject(left)); 6892c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(right)); 6893c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(HCheckInstanceType::NewIsSpecObject(right)); 6894c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HCompareObjectEqAndBranch* result = 6895c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch new(zone()) HCompareObjectEqAndBranch(left, right); 6896c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch result->set_position(expr->position()); 6897c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return ast_context()->ReturnControl(result, expr->id()); 6898c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 6899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 6901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("Unsupported non-primitive compare"); 6902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (type_info.IsString() && oracle()->IsSymbolCompare(expr) && 6904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (op == Token::EQ || op == Token::EQ_STRICT)) { 69053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(left)); 69063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(HCheckInstanceType::NewIsSymbol(left)); 69073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(right)); 69083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch AddInstruction(HCheckInstanceType::NewIsSymbol(right)); 69093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HCompareObjectEqAndBranch* result = 69103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HCompareObjectEqAndBranch(left, right); 69113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 69123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, expr->id()); 6913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6914e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Representation r = ToRepresentation(type_info); 69153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (r.IsTagged()) { 69163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HCompareGeneric* result = 69173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HCompareGeneric(context, left, right, op); 69183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 69193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, expr->id()); 69203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 69213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HCompareIDAndBranch* result = 69223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HCompareIDAndBranch(left, right, op); 69233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->set_position(expr->position()); 69243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch result->SetInputRepresentation(r); 69253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, expr->id()); 69263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 6927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6931592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr, 6932592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* value, 6933592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch NilValue nil) { 6934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 6937592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch EqualityKind kind = 6938592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch expr->op() == Token::EQ_STRICT ? kStrictEquality : kNonStrictEquality; 6939592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HIsNilAndBranch* instr = new(zone()) HIsNilAndBranch(value, kind, nil); 6940592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch instr->set_position(expr->position()); 69413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(instr, expr->id()); 6942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThisFunction(ThisFunction* expr) { 6946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!HasStackOverflow()); 6947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block() != NULL); 6948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current_block()->HasPredecessor()); 6949592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HThisFunction* self = new(zone()) HThisFunction( 6950592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch function_state()->compilation_info()->closure()); 69513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(self, expr->id()); 6952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 69555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitDeclarations(ZoneList<Declaration*>* declarations) { 69565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int length = declarations->length(); 69575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int global_count = 0; 69585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (int i = 0; i < declarations->length(); i++) { 69595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Declaration* decl = declarations->at(i); 69605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration(); 69615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HandleDeclaration(decl->proxy(), 69625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch decl->mode(), 69635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch fun_decl != NULL ? fun_decl->fun() : NULL, 69645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch &global_count); 69655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 69665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 69675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Batch declare global functions and variables. 69685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (global_count > 0) { 69695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<FixedArray> array = 69705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch isolate()->factory()->NewFixedArray(2 * global_count, TENURED); 69715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (int j = 0, i = 0; i < length; i++) { 69725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Declaration* decl = declarations->at(i); 69735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Variable* var = decl->proxy()->var(); 69745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 69755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (var->IsUnallocated()) { 69765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch array->set(j++, *(var->name())); 69775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch FunctionDeclaration* fun_decl = decl->AsFunctionDeclaration(); 69785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (fun_decl == NULL) { 69795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (var->binding_needs_init()) { 69805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // In case this binding needs initialization use the hole. 69815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch array->set_the_hole(j++); 69825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else { 69835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch array->set_undefined(j++); 69845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 69855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } else { 69865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<SharedFunctionInfo> function = 69875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Compiler::BuildFunctionInfo(fun_decl->fun(), info()->script()); 69885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Check for stack-overflow exception. 69895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (function.is_null()) { 69905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch SetStackOverflow(); 69915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return; 69925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 69935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch array->set(j++, *function); 69945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 69955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 69965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 69975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int flags = DeclareGlobalsEvalFlag::encode(info()->is_eval()) | 69985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch DeclareGlobalsNativeFlag::encode(info()->is_native()) | 69995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch DeclareGlobalsLanguageMode::encode(info()->language_mode()); 70005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HInstruction* result = 70015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new(zone()) HDeclareGlobals(environment()->LookupContext(), 70025d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch array, 70035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch flags); 70045d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch AddInstruction(result); 70055d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 7006589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch} 7007589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 7008589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 7009589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochvoid HGraphBuilder::HandleDeclaration(VariableProxy* proxy, 7010592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch VariableMode mode, 70115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch FunctionLiteral* function, 70125d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int* global_count) { 7013589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch Variable* var = proxy->var(); 7014c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch bool binding_needs_init = 7015c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch (mode == CONST || mode == CONST_HARMONY || mode == LET); 7016589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch switch (var->location()) { 7017589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::UNALLOCATED: 70185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ++(*global_count); 70195d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return; 7020589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::PARAMETER: 7021589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOCAL: 7022589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::CONTEXT: 7023c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (binding_needs_init || function != NULL) { 7024589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* value = NULL; 7025c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (function != NULL) { 70265d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_ALIVE(VisitForValue(function)); 7027589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch value = Pop(); 7028c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } else { 7029c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch value = graph()->GetConstantHole(); 7030589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 7031589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (var->IsContextSlot()) { 7032589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch HValue* context = environment()->LookupContext(); 7033c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HStoreContextSlot* store = new HStoreContextSlot( 7034c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch context, var->index(), HStoreContextSlot::kNoCheck, value); 7035589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch AddInstruction(store); 7036592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (store->HasObservableSideEffects()) AddSimulate(proxy->id()); 7037589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else { 7038589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch environment()->Bind(var, value); 7039589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 7040589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } 7041589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch break; 7042589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case Variable::LOOKUP: 7043589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch return Bailout("unsupported lookup slot in declaration"); 70443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 7045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 70485d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitVariableDeclaration(VariableDeclaration* decl) { 70495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch UNREACHABLE(); 70505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 70515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitFunctionDeclaration(FunctionDeclaration* decl) { 70545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch UNREACHABLE(); 70555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 70565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitModuleDeclaration(ModuleDeclaration* decl) { 70595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch UNREACHABLE(); 70605d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 70615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitImportDeclaration(ImportDeclaration* decl) { 70645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch UNREACHABLE(); 70655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 70665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitExportDeclaration(ExportDeclaration* decl) { 70695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch UNREACHABLE(); 70705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 70715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) { 70745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // TODO(rossberg) 70755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 70765d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70775d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70785d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitModuleVariable(ModuleVariable* module) { 70795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // TODO(rossberg) 70805d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 70815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitModulePath(ModulePath* module) { 70845d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // TODO(rossberg) 70855d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 70865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70875d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70885d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::VisitModuleUrl(ModuleUrl* module) { 70895d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // TODO(rossberg) 70905d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 70915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 70925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 7093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Generators for inline runtime functions. 7094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for types. 7095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSmi(CallRuntime* call) { 7096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 70993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HIsSmiAndBranch* result = new(zone()) HIsSmiAndBranch(value); 71003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { 7105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HHasInstanceTypeAndBranch* result = 71093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HHasInstanceTypeAndBranch(value, 71103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FIRST_SPEC_OBJECT_TYPE, 71113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch LAST_SPEC_OBJECT_TYPE); 71123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsFunction(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 HHasInstanceTypeAndBranch* result = 7121592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch new(zone()) HHasInstanceTypeAndBranch(value, JS_FUNCTION_TYPE); 71223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7126e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { 7127e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HHasCachedArrayIndexAndBranch* result = 71313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HHasCachedArrayIndexAndBranch(value); 71323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7136e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsArray(CallRuntime* call) { 7137e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HHasInstanceTypeAndBranch* result = 71413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HHasInstanceTypeAndBranch(value, JS_ARRAY_TYPE); 71423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { 7147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HHasInstanceTypeAndBranch* result = 71513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HHasInstanceTypeAndBranch(value, JS_REGEXP_TYPE); 71523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsObject(CallRuntime* call) { 7157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 71603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HIsObjectAndBranch* result = new(zone()) HIsObjectAndBranch(value); 71613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { 7166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: IsNonNegativeSmi"); 7167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { 7171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(call->arguments()->length() == 1); 7172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* value = Pop(); 71743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HIsUndetectableAndBranch* result = 71753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HIsUndetectableAndBranch(value); 71763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 7181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime* call) { 7182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout( 7183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 7184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 71871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Support for construct call checks. 7188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 7189e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 0); 71908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (function_state()->outer() != NULL) { 71915d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // We are generating graph for inlined function. 71925d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* value = function_state()->is_construct() 71935d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ? graph()->GetConstantTrue() 71945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch : graph()->GetConstantFalse(); 71955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return ast_context()->ReturnValue(value); 71968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 71973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(new(zone()) HIsConstructCallAndBranch, 71983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch call->id()); 71998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 7200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for arguments.length and arguments[?]. 7204e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 720542effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // Our implementation of arguments (based on this stack frame or an 720642effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // adapter below it) does not work for inlined functions. This runtime 720742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // function is blacklisted by AstNode::IsInlineable. 720842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch ASSERT(function_state()->outer() == NULL); 7209e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 0); 72108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 72118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HArgumentsLength* result = new(zone()) HArgumentsLength(elements); 72123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArguments(CallRuntime* call) { 721742effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // Our implementation of arguments (based on this stack frame or an 721842effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // adapter below it) does not work for inlined functions. This runtime 721942effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch // function is blacklisted by AstNode::IsInlineable. 722042effa50d92d47f80404ee63808dbde9921e6202Ben Murdoch ASSERT(function_state()->outer() == NULL); 7221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* index = Pop(); 72248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 72258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); 72268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HAccessArgumentsAt* result = 72278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HAccessArgumentsAt(elements, length, index); 72283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for accessing the class and value fields of an object. 7233e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateClassOf(CallRuntime* call) { 7234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The special form detected by IsClassOfTest is detected before we get here 7235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // and does not cause a bailout. 7236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: ClassOf"); 7237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7240e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateValueOf(CallRuntime* call) { 7241e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 72448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValueOf* result = new(zone()) HValueOf(value); 72453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 72495d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdochvoid HGraphBuilder::GenerateDateField(CallRuntime* call) { 72505d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(call->arguments()->length() == 2); 72515d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT_NE(NULL, call->arguments()->at(1)->AsLiteral()); 72525d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->handle())); 72535d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 72545d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HValue* date = Pop(); 72555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HDateField* result = new(zone()) HDateField(date, index); 72565d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return ast_context()->ReturnInstruction(result, call->id()); 72575d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 72585d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 72595d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 7260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { 7261592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT(call->arguments()->length() == 2); 7262592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7263592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 7264592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* value = Pop(); 7265592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* object = Pop(); 7266592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check if object is a not a smi. 7267592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HIsSmiAndBranch* smicheck = new(zone()) HIsSmiAndBranch(object); 7268592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* if_smi = graph()->CreateBasicBlock(); 7269592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* if_heap_object = graph()->CreateBasicBlock(); 7270592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* join = graph()->CreateBasicBlock(); 7271592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch smicheck->SetSuccessorAt(0, if_smi); 7272592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch smicheck->SetSuccessorAt(1, if_heap_object); 7273592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch current_block()->Finish(smicheck); 7274592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if_smi->Goto(join); 7275592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 7276592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Check if object is a JSValue. 7277592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch set_current_block(if_heap_object); 7278592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HHasInstanceTypeAndBranch* typecheck = 7279592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch new(zone()) HHasInstanceTypeAndBranch(object, JS_VALUE_TYPE); 7280592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* if_js_value = graph()->CreateBasicBlock(); 7281592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* not_js_value = graph()->CreateBasicBlock(); 7282592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch typecheck->SetSuccessorAt(0, if_js_value); 7283592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch typecheck->SetSuccessorAt(1, not_js_value); 7284592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch current_block()->Finish(typecheck); 7285592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch not_js_value->Goto(join); 7286592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 7287592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Create in-object property store to kValueOffset. 7288592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch set_current_block(if_js_value); 7289592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Handle<String> name = isolate()->factory()->undefined_symbol(); 7290592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch AddInstruction(new HStoreNamedField(object, 7291592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch name, 7292592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch value, 7293592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch true, // in-object store. 7294592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch JSValue::kValueOffset)); 7295592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if_js_value->Goto(join); 7296592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch join->SetJoinId(call->id()); 7297592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch set_current_block(join); 7298592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return ast_context()->ReturnValue(value); 7299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for charCodeAt(n). 7303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { 7304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 2); 7305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 73071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* index = Pop(); 73081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* string = Pop(); 73093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 73103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharCodeAt* result = BuildStringCharCodeAt(context, string, index); 73113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n]. 7316e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { 731744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(call->arguments()->length() == 1); 7318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 731944f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* char_code = Pop(); 73203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 73213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharFromCode* result = 73223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HStringCharFromCode(context, char_code); 73233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n]. 7328e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { 732944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(call->arguments()->length() == 2); 7330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 733244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* index = Pop(); 733344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* string = Pop(); 73343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HValue* context = environment()->LookupContext(); 73353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharCodeAt* char_code = BuildStringCharCodeAt(context, string, index); 733644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(char_code); 73373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HStringCharFromCode* result = 73383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HStringCharFromCode(context, char_code); 73393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for object equality testing. 7344e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { 7345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 2); 7346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 7348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 7349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 73503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HCompareObjectEqAndBranch* result = 73513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch new(zone()) HCompareObjectEqAndBranch(left, right); 73523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnControl(result, call->id()); 7353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7356e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateLog(CallRuntime* call) { 7357e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // %_Log is ignored in optimized code. 73583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnValue(graph()->GetConstantUndefined()); 7359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for Math.random(). 7363e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { 7364c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HValue* context = environment()->LookupContext(); 7365c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 7366c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch AddInstruction(global_object); 7367c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HRandom* result = new(zone()) HRandom(global_object); 7368c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringAdd. 7373e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringAdd(CallRuntime* call) { 7374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(2, call->arguments()->length()); 7375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 73778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); 7378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(2); 73793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for SubString. 7384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSubString(CallRuntime* call) { 7385e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(3, call->arguments()->length()); 7386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 73888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); 7389e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(3); 73903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringCompare. 7395e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCompare(CallRuntime* call) { 7396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(2, call->arguments()->length()); 7397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 73998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 74008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::StringCompare, 2); 7401e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(2); 74023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for direct calls from JavaScript to native RegExp code. 7407e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { 7408e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(4, call->arguments()->length()); 7409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 74118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); 7412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(4); 74133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Construct a RegExp exec result with two in-object properties. 7418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { 7419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(3, call->arguments()->length()); 7420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 7422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = 74238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); 7424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(3); 74253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for fast native caches. 7430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { 7431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: GetFromCache"); 7432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for number to string. 7436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateNumberToString(CallRuntime* call) { 7437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 7438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 74408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 74418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::NumberToString, 1); 7442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 74433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast swapping of elements. Takes three expressions, the object and two 7448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// indices. This should only be used if the indices are known to be 7449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// non-negative and within bounds of the elements array at the call site. 7450e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSwapElements(CallRuntime* call) { 7451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: SwapElements"); 7452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call for custom callbacks. 7456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateCallFunction(CallRuntime* call) { 7457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // 1 ~ The function to call is not itself an argument to the call. 7458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int arg_count = call->arguments()->length() - 1; 7459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(arg_count >= 1); // There's always at least a receiver. 7460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < arg_count; ++i) { 7462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); 7463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->last())); 7465592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 7466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* function = Pop(); 7467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 7468592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 7469592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Branch for function proxies, or other non-functions. 7470592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HHasInstanceTypeAndBranch* typecheck = 7471592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch new(zone()) HHasInstanceTypeAndBranch(function, JS_FUNCTION_TYPE); 7472592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* if_jsfunction = graph()->CreateBasicBlock(); 7473592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* if_nonfunction = graph()->CreateBasicBlock(); 7474592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HBasicBlock* join = graph()->CreateBasicBlock(); 7475592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch typecheck->SetSuccessorAt(0, if_jsfunction); 7476592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch typecheck->SetSuccessorAt(1, if_nonfunction); 7477592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch current_block()->Finish(typecheck); 7478592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 7479592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch set_current_block(if_jsfunction); 7480592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HInstruction* invoke_result = AddInstruction( 7481592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch new(zone()) HInvokeFunction(context, function, arg_count)); 7482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Drop(arg_count); 7483592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Push(invoke_result); 7484592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if_jsfunction->Goto(join); 7485592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 7486592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch set_current_block(if_nonfunction); 7487592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HInstruction* call_result = AddInstruction( 7488592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch new(zone()) HCallFunction(context, function, arg_count)); 7489592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Drop(arg_count); 7490592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Push(call_result); 7491592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if_nonfunction->Goto(join); 7492592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 7493592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch set_current_block(join); 7494592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch join->SetJoinId(call->id()); 7495592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return ast_context()->ReturnValue(Pop()); 7496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call to math functions. 7500e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathPow(CallRuntime* call) { 7501e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(2, call->arguments()->length()); 7502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 7504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 7505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 75068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HPower* result = new(zone()) HPower(left, right); 75073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7511e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSin(CallRuntime* call) { 7512e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 7513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 75158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 75168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 7517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::SIN); 7518e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 75193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathCos(CallRuntime* call) { 7524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 7525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 75278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 75288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 7529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::COS); 7530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 75313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7535592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdochvoid HGraphBuilder::GenerateMathTan(CallRuntime* call) { 7536592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 7537592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7538592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HValue* context = environment()->LookupContext(); 7539592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch HCallStub* result = 7540592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 7541592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch result->set_transcendental_type(TranscendentalCache::TAN); 7542592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch Drop(1); 7543592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7544592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch} 7545592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 7546592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 7547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathLog(CallRuntime* call) { 7548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 7549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 7550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HValue* context = environment()->LookupContext(); 75518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 75528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 7553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::LOG); 7554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 75553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { 7560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: MathSqrt"); 7561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check whether two RegExps are equivalent 7565e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { 7566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: IsRegExpEquivalent"); 7567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { 7571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 7572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 7573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HValue* value = Pop(); 75748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); 75753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return ast_context()->ReturnInstruction(result, call->id()); 7576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7579e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { 7580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return Bailout("inlined runtime function: FastAsciiArrayJoin"); 7581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef CHECK_BAILOUT 7585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#undef CHECK_ALIVE 7586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(HEnvironment* outer, 7589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Scope* scope, 7590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> closure) 7591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : closure_(closure), 7592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_(0), 7593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch assigned_variables_(4), 75945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch frame_type_(JS_FUNCTION), 7595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_(0), 7596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch specials_count_(1), 7597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_(0), 7598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_(outer), 7599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pop_count_(0), 7600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch push_count_(0), 76015d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ast_id_(AstNode::kNoNumber) { 7602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); 7603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(const HEnvironment* other) 7607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : values_(0), 7608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch assigned_variables_(0), 76095d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch frame_type_(JS_FUNCTION), 7610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_(0), 7611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch specials_count_(1), 7612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_(0), 7613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_(NULL), 7614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pop_count_(0), 7615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch push_count_(0), 76165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ast_id_(other->ast_id()) { 7617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Initialize(other); 7618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7621c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben MurdochHEnvironment::HEnvironment(HEnvironment* outer, 7622c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Handle<JSFunction> closure, 76235d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch FrameType frame_type, 7624c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch int arguments) 7625c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch : closure_(closure), 7626c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch values_(arguments), 7627c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch assigned_variables_(0), 76285d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch frame_type_(frame_type), 7629c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch parameter_count_(arguments), 7630c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch local_count_(0), 7631c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch outer_(outer), 7632c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch pop_count_(0), 7633c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch push_count_(0), 76345d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ast_id_(AstNode::kNoNumber) { 7635c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch} 7636c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 7637c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 7638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::Initialize(int parameter_count, 7639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int local_count, 7640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int stack_height) { 7641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_ = parameter_count; 7642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_ = local_count; 7643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Avoid reallocating the temporaries' backing store on the first Push. 7645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int total = parameter_count + specials_count_ + local_count + stack_height; 7646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_.Initialize(total + 4); 7647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < total; ++i) values_.Add(NULL); 7648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 76519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Initialize(const HEnvironment* other) { 76529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block closure_ = other->closure(); 76539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_.AddAll(other->values_); 76549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block assigned_variables_.AddAll(other->assigned_variables_); 76555d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch frame_type_ = other->frame_type_; 76569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block parameter_count_ = other->parameter_count_; 76579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block local_count_ = other->local_count_; 76589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy. 76599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block pop_count_ = other->pop_count_; 76609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block push_count_ = other->push_count_; 76619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ast_id_ = other->ast_id_; 76629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 76639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 76649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) { 7666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!block->IsLoopHeader()); 7667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(values_.length() == other->values_.length()); 7668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = values_.length(); 7670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; ++i) { 7671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = values_[i]; 7672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != NULL && value->IsPhi() && value->block() == block) { 7673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is already a phi for the i'th value. 7674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = HPhi::cast(value); 7675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Assert index is correct and that we haven't missed an incoming edge. 7676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->merged_index() == i); 7677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->OperandCount() == block->predecessors()->length()); 7678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(other->values_[i]); 7679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (values_[i] != other->values_[i]) { 7680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is a fresh value on the incoming edge, a phi is needed. 7681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(values_[i] != NULL && other->values_[i] != NULL); 76828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HPhi* phi = new(block->zone()) HPhi(i); 7683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* old_value = values_[i]; 7684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < block->predecessors()->length(); j++) { 7685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(old_value); 7686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(other->values_[i]); 7688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch this->values_[i] = phi; 7689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->AddPhi(phi); 7690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 76959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Bind(int index, HValue* value) { 76969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(value != NULL); 76979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!assigned_variables_.Contains(index)) { 76989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block assigned_variables_.Add(index); 76999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 77009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_[index] = value; 7701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 77049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::HasExpressionAt(int index) const { 7705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return index >= parameter_count_ + specials_count_ + local_count_; 77069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 77079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::ExpressionStackIsEmpty() const { 77105d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(length() >= first_expression_index()); 77115d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return length() == first_expression_index(); 77129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 77139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) { 77169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int count = index_from_top + 1; 77179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index = values_.length() - count; 77189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(HasExpressionAt(index)); 77199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // The push count must include at least the element in question or else 77209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // the new value will not be included in this environment's history. 77219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (push_count_ < count) { 77229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // This is the same effect as popping then re-pushing 'count' elements. 77239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block pop_count_ += (count - push_count_); 77249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block push_count_ = count; 77259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 77269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_[index] = value; 77279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 77289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 77309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Drop(int count) { 77319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = 0; i < count; ++i) { 77329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Pop(); 7733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::Copy() const { 77388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(closure()->GetIsolate()->zone()) HEnvironment(this); 7739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyWithoutHistory() const { 7743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* result = Copy(); 7744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->ClearHistory(); 7745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 7746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const { 7750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* new_env = Copy(); 7751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < values_.length(); ++i) { 77528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HPhi* phi = new(loop_header->zone()) HPhi(i); 7753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(values_[i]); 7754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_env->values_[i] = phi; 7755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_header->AddPhi(phi); 7756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_env->ClearHistory(); 7758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new_env; 7759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 77625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen MurdochHEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer, 77635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch Handle<JSFunction> target, 77645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch FrameType frame_type, 77655d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch int arguments) const { 77665d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HEnvironment* new_env = new(closure()->GetIsolate()->zone()) 77675d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch HEnvironment(outer, target, frame_type, arguments + 1); 77685d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch for (int i = 0; i <= arguments; ++i) { // Include receiver. 77695d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new_env->Push(ExpressionStackAt(arguments - i)); 77705d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 77715d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch new_env->ClearHistory(); 77725d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch return new_env; 77735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch} 77745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 77755d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 7776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben MurdochHEnvironment* HEnvironment::CopyForInlining( 7777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<JSFunction> target, 7778c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch int arguments, 7779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FunctionLiteral* function, 7780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch HConstant* undefined, 77815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch CallKind call_kind, 77825d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch bool is_construct) const { 77835d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ASSERT(frame_type() == JS_FUNCTION); 7784c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 7785c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch Zone* zone = closure()->GetIsolate()->zone(); 7786c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 7787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Outer environment is a copy of this one without the arguments. 7788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity = function->scope()->num_parameters(); 7789c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 7790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* outer = Copy(); 7791c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch outer->Drop(arguments + 1); // Including receiver. 7792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer->ClearHistory(); 7793c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 77945d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (is_construct) { 77955d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Create artificial constructor stub environment. The receiver should 77965d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // actually be the constructor function, but we pass the newly allocated 77975d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // object instead, DoComputeConstructStubFrame() relies on that. 77985d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments); 77995d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 78005d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 7801c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch if (arity != arguments) { 7802c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch // Create artificial arguments adaptation environment. 78035d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments); 7804c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch } 7805c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 78068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HEnvironment* inner = 78078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone) HEnvironment(outer, function->scope(), target); 7808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the argument values from the original environment. 78093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (int i = 0; i <= arity; ++i) { // Include receiver. 7810c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch HValue* push = (i <= arguments) ? 7811c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch ExpressionStackAt(arguments - i) : undefined; 78123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch inner->SetValueAt(i, push); 78133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 78143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If the function we are inlining is a strict mode function or a 78153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // builtin function, pass undefined as the receiver for function 78163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // calls (instead of the global receiver). 7817592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if ((target->shared()->native() || !function->is_classic_mode()) && 78185d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch call_kind == CALL_AS_FUNCTION && !is_construct) { 7819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inner->SetValueAt(0, undefined); 7820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7821c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch inner->SetValueAt(arity + 1, LookupContext()); 7822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = arity + 2; i < inner->length(); ++i) { 7823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch inner->SetValueAt(i, undefined); 7824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 78268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch inner->set_ast_id(AstNode::kFunctionEntryId); 7827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return inner; 7828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintTo(StringStream* stream) { 78329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = 0; i < length(); i++) { 7833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (i == 0) stream->Add("parameters\n"); 7834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i == parameter_count()) stream->Add("specials\n"); 7835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i == parameter_count() + specials_count()) stream->Add("locals\n"); 7836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (i == parameter_count() + specials_count() + local_count()) { 7837c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch stream->Add("expressions\n"); 7838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* val = values_.at(i); 7840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("%d: ", i); 7841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (val != NULL) { 7842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch val->PrintNameTo(stream); 7843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 7844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("NULL"); 7845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("\n"); 7847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7848c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch PrintF("\n"); 7849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintToStd() { 7853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HeapStringAllocator string_allocator; 7854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StringStream trace(&string_allocator); 7855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintTo(&trace); 7856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("%s", *trace.ToCString()); 7857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceCompilation(FunctionLiteral* function) { 7861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "compilation"); 7862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = function->debug_name(); 7863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", *name->ToCString()); 7864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("method", *name->ToCString()); 7865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); 7866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLithium(const char* name, LChunk* chunk) { 7870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Trace(name, chunk->graph(), chunk); 7871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceHydrogen(const char* name, HGraph* graph) { 7875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Trace(name, graph, NULL); 7876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { 7880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "cfg"); 7881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", name); 7882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HBasicBlock*>* blocks = graph->blocks(); 7883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks->length(); i++) { 7884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* current = blocks->at(i); 7885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag block_tag(this, "block"); 7886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("name", current->block_id()); 7887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty("from_bci", -1); 7888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty("to_bci", -1); 7889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!current->predecessors()->is_empty()) { 7891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIndent(); 7892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("predecessors"); 7893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < current->predecessors()->length(); ++j) { 7894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id()); 7895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("\n"); 7897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 7898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("predecessors"); 7899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 79013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (current->end()->SuccessorCount() == 0) { 7902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("successors"); 79033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 79043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch PrintIndent(); 79053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trace_.Add("successors"); 79063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) { 79073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trace_.Add(" \"B%d\"", it.Current()->block_id()); 79083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 79093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch trace_.Add("\n"); 7910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("xhandlers"); 79135d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch const char* flags = current->IsLoopSuccessorDominator() 79145d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch ? "dom-loop-succ" 79155d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch : ""; 79165d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch PrintStringProperty("flags", flags); 7917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->dominator() != NULL) { 7919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("dominator", current->dominator()->block_id()); 7920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7922589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch PrintIntProperty("loop_depth", current->LoopNestingDepth()); 7923589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 7924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk != NULL) { 7925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int first_index = current->first_instruction_index(); 7926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_index = current->last_instruction_index(); 7927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty( 7928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "first_lir_id", 7929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(first_index).Value()); 7930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty( 7931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "last_lir_id", 7932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(last_index).Value()); 7933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 7936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag states_tag(this, "states"); 7937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag locals_tag(this, "locals"); 7938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int total = current->phis()->length(); 7939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintIntProperty("size", current->phis()->length()); 7940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintStringProperty("method", "None"); 7941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < total; ++j) { 7942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = current->phis()->at(j); 7943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintIndent(); 7944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d ", phi->merged_index()); 7945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->PrintNameTo(&trace_); 7946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" "); 7947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->PrintTo(&trace_); 7948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("\n"); 7949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 7953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag HIR_tag(this, "HIR"); 7954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instruction = current->first(); 7955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instruction != NULL) { 7956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int bci = 0; 7957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int uses = instruction->UseCount(); 7958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintIndent(); 7959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d %d ", bci, uses); 7960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction->PrintNameTo(&trace_); 7961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" "); 7962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction->PrintTo(&trace_); 7963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" <|@\n"); 7964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction = instruction->next(); 7965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk != NULL) { 7970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag LIR_tag(this, "LIR"); 7971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int first_index = current->first_instruction_index(); 7972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_index = current->last_instruction_index(); 7973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first_index != -1 && last_index != -1) { 7974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<LInstruction*>* instructions = chunk->instructions(); 7975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = first_index; i <= last_index; ++i) { 7976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LInstruction* linstr = instructions->at(i); 7977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (linstr != NULL) { 7978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintIndent(); 7979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d ", 7980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(i).Value()); 7981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch linstr->PrintTo(&trace_); 7982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" <|@\n"); 7983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 7989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 7991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) { 7992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "intervals"); 7993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", name); 7994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 799544f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges(); 7996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < fixed_d->length(); ++i) { 7997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(fixed_d->at(i), "fixed"); 7998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 7999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 800044f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges(); 8001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < fixed->length(); ++i) { 8002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(fixed->at(i), "fixed"); 8003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges(); 8006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < live_ranges->length(); ++i) { 8007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(live_ranges->at(i), "object"); 8008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRange(LiveRange* range, const char* type) { 8013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range != NULL && !range->IsEmpty()) { 8014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PrintIndent(); 8015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d %s", range->id(), type); 8016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range->HasRegisterAssigned()) { 80175d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch LOperand* op = range->CreateAssignedOperand(ZONE); 8018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int assigned_reg = op->index(); 8019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op->IsDoubleRegister()) { 8020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"%s\"", 8021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoubleRegister::AllocationIndexToString(assigned_reg)); 8022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsRegister()); 8024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg)); 8025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (range->IsSpilled()) { 8027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op = range->TopLevel()->GetSpillOperand(); 8028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op->IsDoubleStackSlot()) { 8029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"double_stack:%d\"", op->index()); 8030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsStackSlot()); 8032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"stack:%d\"", op->index()); 8033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int parent_index = -1; 8036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range->IsChild()) { 8037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parent_index = range->parent()->id(); 8038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parent_index = range->id(); 8040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op = range->FirstHint(); 8042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int hint_index = -1; 80435d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (op != NULL && op->IsUnallocated()) { 80445d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch hint_index = LUnallocated::cast(op)->virtual_register(); 80455d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch } 8046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" %d %d", parent_index, hint_index); 8047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UseInterval* cur_interval = range->first_interval(); 8048e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (cur_interval != NULL && range->Covers(cur_interval->start())) { 8049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" [%d, %d[", 8050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval->start().Value(), 8051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval->end().Value()); 8052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval = cur_interval->next(); 8053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UsePosition* current_pos = range->first_pos(); 8056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current_pos != NULL) { 8057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) { 8058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" %d M", current_pos->pos().Value()); 8059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_pos = current_pos->next(); 8061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"\"\n"); 8064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::FlushToFile() { 8069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendChars(filename_, *trace_.ToCString(), trace_.length(), false); 8070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Reset(); 8071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 807444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HStatistics::Initialize(CompilationInfo* info) { 807544f0eee88ff00398ff7f715fab053374d808c90dSteve Block source_size_ += info->shared_info()->SourceSize(); 807644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 807744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 807844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 8079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStatistics::Print() { 8080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Timing results:\n"); 8081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int64_t sum = 0; 8082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < timing_.length(); ++i) { 8083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch sum += timing_[i]; 8084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < names_.length(); ++i) { 8087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("%30s", names_[i]); 8088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double ms = static_cast<double>(timing_[i]) / 1000; 8089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double percent = static_cast<double>(timing_[i]) * 100 / sum; 8090b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF(" - %7.3f ms / %4.1f %% ", ms, percent); 8091b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 8092b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch unsigned size = sizes_[i]; 8093b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch double size_percent = static_cast<double>(size) * 100 / total_size_; 8094b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF(" %8u bytes / %4.1f %%\n", size, size_percent); 8095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 809644f0eee88ff00398ff7f715fab053374d808c90dSteve Block double source_size_in_kb = static_cast<double>(source_size_) / 1024; 809744f0eee88ff00398ff7f715fab053374d808c90dSteve Block double normalized_time = source_size_in_kb > 0 809844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? (static_cast<double>(sum) / 1000) / source_size_in_kb 809944f0eee88ff00398ff7f715fab053374d808c90dSteve Block : 0; 810044f0eee88ff00398ff7f715fab053374d808c90dSteve Block double normalized_bytes = source_size_in_kb > 0 810144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? total_size_ / source_size_in_kb 810244f0eee88ff00398ff7f715fab053374d808c90dSteve Block : 0; 810344f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%30s - %7.3f ms %7.3f bytes\n", "Sum", 810444f0eee88ff00398ff7f715fab053374d808c90dSteve Block normalized_time, normalized_bytes); 8105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("---------------------------------------------------------------\n"); 8106b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n", 8107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "Total", 8108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<double>(total_) / 1000, 8109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<double>(total_) / full_code_gen_); 8110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8113b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) { 8114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (name == HPhase::kFullCodeGen) { 8115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch full_code_gen_ += ticks; 8116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (name == HPhase::kTotal) { 8117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch total_ += ticks; 8118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 8119b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch total_size_ += size; 8120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < names_.length(); ++i) { 8121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (names_[i] == name) { 8122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch timing_[i] += ticks; 8123b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch sizes_[i] += size; 8124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 8125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch names_.Add(name); 8128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch timing_.Add(ticks); 8129b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch sizes_.Add(size); 8130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kFullCodeGen = "Full code generator"; 8135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kTotal = "Total"; 8136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::Begin(const char* name, 8139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph, 8140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LChunk* chunk, 8141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LAllocator* allocator) { 8142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch name_ = name; 8143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_ = graph; 8144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk_ = chunk; 8145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch allocator_ = allocator; 8146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator != NULL && chunk_ == NULL) { 8147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk_ = allocator->chunk(); 8148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 814944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_hydrogen_stats) start_ = OS::Ticks(); 8150b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch start_allocation_size_ = Zone::allocation_size_; 8151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::End() const { 815544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_hydrogen_stats) { 8156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int64_t end = OS::Ticks(); 8157b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch unsigned size = Zone::allocation_size_ - start_allocation_size_; 8158b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch HStatistics::Instance()->SaveTiming(name_, end - start_, size); 8159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 81615d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // Produce trace output if flag is set so that the first letter of the 81625d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch // phase name matches the command line parameter FLAG_trace_phase. 81635d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch if (FLAG_trace_hydrogen && 81645d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch OS::StrChr(const_cast<char*>(FLAG_trace_phase), name_[0]) != NULL) { 8165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_); 8166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_); 8167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator_ != NULL) { 8168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HTracer::Instance()->TraceLiveRanges(name_, allocator_); 8169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 8171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 8173592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch if (graph_ != NULL) graph_->Verify(false); // No full verify. 8174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator_ != NULL) allocator_->Verify(); 8175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 8176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 8177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 8178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} } // namespace v8::internal 8179