hydrogen.cc revision 8b112d2025046f85ef7f6be087c6129c872ebad2
1b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch// Copyright 2011 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 "data-flow.h" 33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h" 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hashmap.h" 35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "lithium-allocator.h" 36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "parser.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), 72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch is_inline_return_target_(false) { 73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AttachLoopInformation() { 77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsLoopHeader()); 788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch loop_information_ = new(zone()) HLoopInformation(this); 79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::DetachLoopInformation() { 83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsLoopHeader()); 84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_information_ = NULL; 85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddPhi(HPhi* phi) { 89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsStartBlock()); 90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_.Add(phi); 91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->SetBlock(this); 92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RemovePhi(HPhi* phi) { 96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->block() == this); 97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phis_.Contains(phi)); 9844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(phi->HasNoUses() || !phi->is_live()); 99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->ClearOperands(); 100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_.RemoveElement(phi); 101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->SetBlock(NULL); 102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddInstruction(HInstruction* instr) { 106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsStartBlock() || !IsFinished()); 107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!instr->IsLinked()); 108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsFinished()); 109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first_ == NULL) { 1108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HBlockEntry* entry = new(zone()) HBlockEntry(); 111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch entry->InitializeAsFirst(this); 112e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch first_ = last_ = entry; 113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 114e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch instr->InsertAfter(last_); 115e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch last_ = instr; 116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 11944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHDeoptimize* HBasicBlock::CreateDeoptimize() { 12044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(HasEnvironment()); 12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block HEnvironment* environment = last_environment(); 12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HDeoptimize* instr = new(zone()) HDeoptimize(environment->length()); 12444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 12544f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < environment->length(); i++) { 12644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* val = environment->values()->at(i); 12744f0eee88ff00398ff7f715fab053374d808c90dSteve Block instr->AddEnvironmentValue(val); 12844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 12944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return instr; 13144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 13244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 13344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSimulate* HBasicBlock::CreateSimulate(int id) { 135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(HasEnvironment()); 136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* environment = last_environment(); 137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(id == AstNode::kNoNumber || 138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment->closure()->shared()->VerifyBailoutId(id)); 139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int push_count = environment->push_count(); 141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int pop_count = environment->pop_count(); 142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HSimulate* instr = new(zone()) HSimulate(id, pop_count); 144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = push_count - 1; i >= 0; --i) { 145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->AddPushedValue(environment->ExpressionStackAt(i)); 146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < environment->assigned_variables()->length(); ++i) { 148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = environment->assigned_variables()->at(i); 149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->AddAssignedValue(index, environment->Lookup(index)); 150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment->ClearHistory(); 152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Finish(HControlInstruction* end) { 157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsFinished()); 158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(end); 159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch end_ = end; 160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (end->FirstSuccessor() != NULL) { 161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch end->FirstSuccessor()->RegisterPredecessor(this); 162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (end->SecondSuccessor() != NULL) { 163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch end->SecondSuccessor()->RegisterPredecessor(this); 164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) { 17044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (block->IsInlineReturnTarget()) { 1718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HLeaveInlined); 17244f0eee88ff00398ff7f715fab053374d808c90dSteve Block last_environment_ = last_environment()->outer(); 17344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(AstNode::kNoNumber); 1758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGoto* instr = new(zone()) HGoto(block); 176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_include_stack_check(include_stack_check); 177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Finish(instr); 178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 18144f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 18244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(target->IsInlineReturnTarget()); 18344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(return_value != NULL); 1848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HLeaveInlined); 18544f0eee88ff00398ff7f715fab053374d808c90dSteve Block last_environment_ = last_environment()->outer(); 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 200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::SetJoinId(int 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() 210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ->VerifyBailoutId(id)); 211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch simulate->set_ast_id(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 226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) { 227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsLoopHeader()); 228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetJoinId(stmt->EntryId()); 230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (predecessors()->length() == 1) { 231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // This is a degenerated loop. 232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DetachLoopInformation(); 233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only the first entry into the loop is from outside the loop. All other 237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // entries must be back edges. 238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 1; i < predecessors()->length(); ++i) { 239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_information()->RegisterBackEdge(predecessors()->at(i)); 240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { 2458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (HasPredecessor()) { 246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only loop header blocks can have a predecessor added after 247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // instructions have been added to the block (they have phis for all 248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // values in the environment, these phis may be eliminated later). 249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsLoopHeader() || first_ == NULL); 250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* incoming_env = pred->last_environment(); 251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (IsLoopHeader()) { 2529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(phis()->length() == incoming_env->length()); 253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phis_.length(); ++i) { 254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_[i]->AddInput(incoming_env->values()->at(i)); 255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_environment()->AddIncomingEdge(this, pred->last_environment()); 258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (!HasEnvironment() && !IsFinished()) { 260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsLoopHeader()); 261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetInitialEnvironment(pred->last_environment()->Copy()); 262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch predecessors_.Add(pred); 265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddDominatedBlock(HBasicBlock* block) { 269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!dominated_blocks_.Contains(block)); 270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keep the list of dominated blocks sorted such that if there is two 271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // succeeding block in this list, the predecessor is before the successor. 272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = 0; 273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (index < dominated_blocks_.length() && 274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominated_blocks_[index]->block_id() < block->block_id()) { 275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ++index; 276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominated_blocks_.InsertAt(index, block); 278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AssignCommonDominator(HBasicBlock* other) { 282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (dominator_ == NULL) { 283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_ = other; 284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->AddDominatedBlock(this); 285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (other->dominator() != NULL) { 286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* first = dominator_; 287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* second = other; 288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (first != second) { 290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first->block_id() > second->block_id()) { 291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first = first->dominator(); 292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch second = second->dominator(); 294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(first != NULL && second != NULL); 296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (dominator_ != first) { 299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(dominator_->dominated_blocks_.Contains(this)); 300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_->dominated_blocks_.RemoveElement(this); 301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_ = first; 302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first->AddDominatedBlock(this); 303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const { 309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < predecessors_.length(); ++i) { 310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (predecessors_[i] == predecessor) return i; 311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return -1; 314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Verify() { 319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that every block is finished. 320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsFinished()); 321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(block_id() >= 0); 32244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 32344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the incoming edges are in edge split form. 32444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (predecessors_.length() > 1) { 32544f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < predecessors_.length(); ++i) { 32644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(predecessors_[i]->end()->SecondSuccessor() == NULL); 32744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 32844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::RegisterBackEdge(HBasicBlock* block) { 334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch this->back_edges_.Add(block); 335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddBlock(block); 336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HLoopInformation::GetLastBackEdge() const { 340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int max_id = -1; 341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* result = NULL; 342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < back_edges_.length(); ++i) { 343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* cur = back_edges_[i]; 344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (cur->block_id() > max_id) { 345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch max_id = cur->block_id(); 346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = cur; 347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::AddBlock(HBasicBlock* block) { 354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block == loop_header()) return; 355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->parent_loop_header() == loop_header()) return; 356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->parent_loop_header() != NULL) { 357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddBlock(block->parent_loop_header()); 358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->set_parent_loop_header(loop_header()); 360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.Add(block); 361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < block->predecessors()->length(); ++i) { 362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddBlock(block->predecessors()->at(i)); 363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Checks reachability of the blocks in this graph and stores a bit in 371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the BitVector "reachable()" for every block that can be reached 372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from the start block of the graph. If "dont_visit" is non-null, the given 373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// block is treated as if it would not be part of the graph. "visited_count()" 374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// returns the number of reachable blocks. 375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass ReachabilityAnalyzer BASE_EMBEDDED { 376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ReachabilityAnalyzer(HBasicBlock* entry_block, 378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int block_count, 379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dont_visit) 380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : visited_count_(0), 381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stack_(16), 382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reachable_(block_count), 383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dont_visit_(dont_visit) { 384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushBlock(entry_block); 385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Analyze(); 386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int visited_count() const { return visited_count_; } 389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const BitVector* reachable() const { return &reachable_; } 390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PushBlock(HBasicBlock* block) { 393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block != NULL && block != dont_visit_ && 394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !reachable_.Contains(block->block_id())) { 395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reachable_.Add(block->block_id()); 396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stack_.Add(block); 397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visited_count_++; 398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze() { 402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!stack_.is_empty()) { 403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HControlInstruction* end = stack_.RemoveLast()->end(); 404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushBlock(end->FirstSuccessor()); 405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushBlock(end->SecondSuccessor()); 406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int visited_count_; 410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*> stack_; 411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector reachable_; 412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dont_visit_; 413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Verify() const { 417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); i++) { 418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = blocks_.at(i); 419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->Verify(); 421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that every block contains at least one node and that only the last 423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // node is a control instruction. 424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = block->first(); 425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current != NULL && current->IsBlockEntry()); 426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT((current->next() == NULL) == current->IsControlInstruction()); 428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current->block() == block); 429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->Verify(); 430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that successors are correctly set. 434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* first = block->end()->FirstSuccessor(); 435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* second = block->end()->SecondSuccessor(); 436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(second == NULL || first != NULL); 437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that the predecessor array is correct. 439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first != NULL) { 440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(first->predecessors()->Contains(block)); 441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (second != NULL) { 442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(second->predecessors()->Contains(block)); 443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that phis have correct arguments. 447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < block->phis()->length(); j++) { 448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = block->phis()->at(j); 449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->Verify(); 450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that all join blocks have predecessors that end with an 453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // unconditional goto and agree on their environment node id. 454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->predecessors()->length() >= 2) { 455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int id = block->predecessors()->first()->last_environment()->ast_id(); 456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int k = 0; k < block->predecessors()->length(); k++) { 457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* predecessor = block->predecessors()->at(k); 458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(predecessor->end()->IsGoto()); 459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(predecessor->last_environment()->ast_id() == id); 460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check special property of first block to have no predecessors. 465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(blocks_.at(0)->predecessors()->is_empty()); 466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that the graph is fully connected. 468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL); 469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(analyzer.visited_count() == blocks_.length()); 470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that entry block dominator is NULL. 472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(entry_block_->dominator() == NULL); 473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check dominators. 475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = blocks_.at(i); 477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->dominator() == NULL) { 478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only start block may have no dominator assigned to. 479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(i == 0); 480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Assert that block is unreachable if dominator must not be visited. 482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ReachabilityAnalyzer dominator_analyzer(entry_block_, 483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.length(), 484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->dominator()); 485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id())); 486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, 494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Object* value) { 495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!pointer->is_set()) { 4968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HConstant* constant = new(zone()) HConstant(Handle<Object>(value), 4978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Representation::Tagged()); 498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch constant->InsertAfter(GetConstantUndefined()); 499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pointer->set(constant); 500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return pointer->get(); 502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant1() { 506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return GetConstant(&constant_1_, Smi::FromInt(1)); 507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantMinus1() { 511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return GetConstant(&constant_minus1_, Smi::FromInt(-1)); 512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantTrue() { 51644f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetConstant(&constant_true_, isolate()->heap()->true_value()); 517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantFalse() { 52144f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetConstant(&constant_false_, isolate()->heap()->false_value()); 522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 525e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateJoin(HBasicBlock* first, 526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* second, 527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int join_id) { 528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (first == NULL) { 529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return second; 530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (second == NULL) { 531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return first; 532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* join_block = graph_->CreateBasicBlock(); 534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch first->Goto(join_block); 535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch second->Goto(join_block); 536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch join_block->SetJoinId(join_id); 537e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return join_block; 538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::JoinContinue(IterationStatement* statement, 543e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* exit_block, 544e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* continue_block) { 545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (continue_block != NULL) { 546e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (exit_block != NULL) exit_block->Goto(continue_block); 547e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch continue_block->SetJoinId(statement->ContinueId()); 548e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return continue_block; 549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 550e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return exit_block; 551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 554e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateLoop(IterationStatement* statement, 555e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_entry, 556e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_exit, 557e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_successor, 558e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* break_block) { 559e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (body_exit != NULL) body_exit->Goto(loop_entry, true); 560e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_entry->PostProcessLoopHeader(statement); 561e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (break_block != NULL) { 562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (loop_successor != NULL) loop_successor->Goto(break_block); 563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break_block->SetJoinId(statement->ExitId()); 564e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return break_block; 565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 566e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return loop_successor; 567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 570e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HBasicBlock::FinishExit(HControlInstruction* instruction) { 571e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Finish(instruction); 572e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ClearEnvironment(); 573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHGraph::HGraph(CompilationInfo* info) 57744f0eee88ff00398ff7f715fab053374d808c90dSteve Block : isolate_(info->isolate()), 578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next_block_id_(0), 57944f0eee88ff00398ff7f715fab053374d808c90dSteve Block entry_block_(NULL), 580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_(8), 581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_(16), 582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi_list_(NULL) { 5838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch start_environment_ = 5848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HEnvironment(NULL, info->scope(), info->closure()); 5858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch start_environment_->set_ast_id(AstNode::kFunctionEntryId); 58644f0eee88ff00398ff7f715fab053374d808c90dSteve Block entry_block_ = CreateBasicBlock(); 58744f0eee88ff00398ff7f715fab053374d808c90dSteve Block entry_block_->SetInitialEnvironment(start_environment_); 588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 591e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHandle<Code> HGraph::Compile(CompilationInfo* info) { 592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int values = GetMaximumValueID(); 593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (values > LAllocator::max_initial_value_ids()) { 594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_bailout) PrintF("Function is too big\n"); 595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Handle<Code>::null(); 596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LAllocator allocator(values, this); 599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LChunkBuilder builder(info, this, &allocator); 600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LChunk* chunk = builder.Build(); 601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk == NULL) return Handle<Code>::null(); 602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!FLAG_alloc_lithium) return Handle<Code>::null(); 604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch allocator.Allocate(chunk); 606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!FLAG_use_lithium) return Handle<Code>::null(); 608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch MacroAssembler assembler(info->isolate(), NULL, 0); 610e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch LCodeGen generator(chunk, &assembler, info); 611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_eliminate_empty_blocks) { 613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk->MarkEmptyBlocks(); 614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (generator.GenerateCode()) { 617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_codegen) { 618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Crankshaft Compiler - "); 619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 620e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CodeGenerator::MakeCodePrologue(info); 621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Code::Flags flags = 622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Code::ComputeFlags(Code::OPTIMIZED_FUNCTION, NOT_IN_LOOP); 623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Code> code = 624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CodeGenerator::MakeCodeEpilogue(&assembler, flags, info); 625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch generator.FinishCode(code); 626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CodeGenerator::PrintCode(code, info); 627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return code; 628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Handle<Code>::null(); 630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraph::CreateBasicBlock() { 6348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HBasicBlock* result = new(zone()) HBasicBlock(this); 635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.Add(result); 636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Canonicalize() { 641e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!FLAG_use_canonicalizing) return; 642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Canonicalize", this); 643e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < blocks()->length(); ++i) { 644e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HInstruction* instr = blocks()->at(i)->first(); 645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (instr != NULL) { 646e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HValue* value = instr->Canonicalize(); 647e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (value != instr) instr->ReplaceAndDelete(value); 648e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch instr = instr->next(); 649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::OrderBlocks() { 655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Block ordering"); 656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector visited(blocks_.length()); 657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*> reverse_result(8); 659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* start = blocks_[0]; 660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(start, &visited, &reverse_result, NULL); 661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 66244f0eee88ff00398ff7f715fab053374d808c90dSteve Block blocks_.Rewind(0); 663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = 0; 664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = reverse_result.length() - 1; i >= 0; --i) { 665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* b = reverse_result[i]; 666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.Add(b); 667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch b->set_block_id(index++); 668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PostorderLoopBlocks(HLoopInformation* loop, 673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector* visited, 674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*>* order, 675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header) { 676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < loop->blocks()->length(); ++i) { 677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* b = loop->blocks()->at(i); 678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(b->end()->SecondSuccessor(), visited, order, loop_header); 679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(b->end()->FirstSuccessor(), visited, order, loop_header); 680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (b->IsLoopHeader() && b != loop->loop_header()) { 681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PostorderLoopBlocks(b->loop_information(), visited, order, loop_header); 682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Postorder(HBasicBlock* block, 688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector* visited, 689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*>* order, 690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header) { 691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block == NULL || visited->Contains(block->block_id())) return; 692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->parent_loop_header() != loop_header) return; 693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visited->Add(block->block_id()); 694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PostorderLoopBlocks(block->loop_information(), visited, order, loop_header); 696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(block->end()->SecondSuccessor(), visited, order, block); 697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(block->end()->FirstSuccessor(), visited, order, block); 698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(block->end()->SecondSuccessor(), visited, order, loop_header); 700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(block->end()->FirstSuccessor(), visited, order, loop_header); 701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(block->end()->FirstSuccessor() == NULL || 703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch order->Contains(block->end()->FirstSuccessor()) || 704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->end()->FirstSuccessor()->IsLoopHeader()); 705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(block->end()->SecondSuccessor() == NULL || 706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch order->Contains(block->end()->SecondSuccessor()) || 707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->end()->SecondSuccessor()->IsLoopHeader()); 708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch order->Add(block); 709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::AssignDominators() { 713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Assign dominators", this); 714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (blocks_[i]->IsLoopHeader()) { 716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first()); 717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) { 719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); 720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::EliminateRedundantPhis() { 72744f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhase phase("Redundant phi elimination", this); 728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Worklist of phis that can potentially be eliminated. Initialized 730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // with all phi nodes. When elimination of a phi node modifies 731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // another phi node the modified phi node is added to the worklist. 732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HPhi*> worklist(blocks_.length()); 733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist.AddAll(*blocks_[i]->phis()); 735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!worklist.is_empty()) { 738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = worklist.RemoveLast(); 739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = phi->block(); 740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Skip phi node if it was already replaced. 742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block == NULL) continue; 743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get replacement value if phi is redundant. 745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = phi->GetRedundantReplacement(); 746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != NULL) { 748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Iterate through uses finding the ones that should be 749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // replaced. 75044f0eee88ff00398ff7f715fab053374d808c90dSteve Block SmallPointerList<HValue>* uses = phi->uses(); 75144f0eee88ff00398ff7f715fab053374d808c90dSteve Block while (!uses->is_empty()) { 75244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* use = uses->RemoveLast(); 75344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (use != NULL) { 75444f0eee88ff00398ff7f715fab053374d808c90dSteve Block phi->ReplaceAtUse(use, value); 75544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (use->IsPhi()) worklist.Add(HPhi::cast(use)); 756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->RemovePhi(phi); 75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 76144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 76244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 76344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 76444f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HGraph::EliminateUnreachablePhis() { 76544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhase phase("Unreachable phi elimination", this); 76644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 76744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Initialize worklist. 76844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZoneList<HPhi*> phi_list(blocks_.length()); 76944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZoneList<HPhi*> worklist(blocks_.length()); 77044f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < blocks_.length(); ++i) { 77144f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int j = 0; j < blocks_[i]->phis()->length(); j++) { 77244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhi* phi = blocks_[i]->phis()->at(j); 77344f0eee88ff00398ff7f715fab053374d808c90dSteve Block phi_list.Add(phi); 7741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We can't eliminate phis in the receiver position in the environment 7751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // because in case of throwing an error we need this value to 7761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // construct a stack trace. 77744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (phi->HasRealUses() || phi->IsReceiver()) { 77844f0eee88ff00398ff7f715fab053374d808c90dSteve Block phi->set_is_live(true); 77944f0eee88ff00398ff7f715fab053374d808c90dSteve Block worklist.Add(phi); 78044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 78144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 78244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 78344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 78444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Iteratively mark live phis. 78544f0eee88ff00398ff7f715fab053374d808c90dSteve Block while (!worklist.is_empty()) { 78644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhi* phi = worklist.RemoveLast(); 78744f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < phi->OperandCount(); i++) { 78844f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* operand = phi->OperandAt(i); 78944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (operand->IsPhi() && !HPhi::cast(operand)->is_live()) { 79044f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhi::cast(operand)->set_is_live(true); 79144f0eee88ff00398ff7f715fab053374d808c90dSteve Block worklist.Add(HPhi::cast(operand)); 79244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 79544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 79644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Remove unreachable phis. 79744f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < phi_list.length(); i++) { 79844f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhi* phi = phi_list[i]; 79944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!phi->is_live()) { 80044f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* block = phi->block(); 801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->RemovePhi(phi); 802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->RecordDeletedPhi(phi->merged_index()); 803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraph::CollectPhis() { 80944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int block_count = blocks_.length(); 81044f0eee88ff00398ff7f715fab053374d808c90dSteve Block phi_list_ = new ZoneList<HPhi*>(block_count); 81144f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < block_count; ++i) { 81244f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int j = 0; j < blocks_[i]->phis()->length(); ++j) { 81344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HPhi* phi = blocks_[i]->phis()->at(j); 814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi_list_->Add(phi); 815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't support phi uses of arguments for now. 816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (phi->CheckFlag(HValue::kIsArguments)) return false; 817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InferTypes(ZoneList<HValue*>* worklist) { 824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector in_worklist(GetMaximumValueID()); 825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < worklist->length(); ++i) { 826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!in_worklist.Contains(worklist->at(i)->id())); 827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist.Add(worklist->at(i)->id()); 828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!worklist->is_empty()) { 831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* current = worklist->RemoveLast(); 832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist.Remove(current->id()); 833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->UpdateInferredType()) { 834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < current->uses()->length(); j++) { 835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = current->uses()->at(j); 836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!in_worklist.Contains(use->id())) { 837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist.Add(use->id()); 838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist->Add(use); 839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HRangeAnalysis BASE_EMBEDDED { 847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {} 849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(); 851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void TraceRange(const char* msg, ...); 854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(HBasicBlock* block); 8551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block void InferControlFlowRange(HTest* test, HBasicBlock* dest); 856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferControlFlowRange(Token::Value op, HValue* value, HValue* other); 857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferPhiRange(HPhi* phi); 858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferRange(HValue* value); 859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void RollBackTo(int index); 860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AddRange(HValue* value, Range* range); 861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> changed_ranges_; 864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::TraceRange(const char* msg, ...) { 868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_range) { 869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_list arguments; 870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_start(arguments, msg); 871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch OS::VPrint(msg, arguments); 872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_end(arguments); 873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze() { 878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Range analysis", graph_); 879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Analyze(graph_->blocks()->at(0)); 880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze(HBasicBlock* block) { 884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Analyzing block B%d\n", block->block_id()); 885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_changed_range = changed_ranges_.length() - 1; 887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Infer range based on control flow. 889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->predecessors()->length() == 1) { 890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* pred = block->predecessors()->first(); 8911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (pred->end()->IsTest()) { 8921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block InferControlFlowRange(HTest::cast(pred->end()), block); 893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Process phi instructions. 897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < block->phis()->length(); ++i) { 898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = block->phis()->at(i); 899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferPhiRange(phi); 900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Go through all instructions of the current block. 903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != block->end()) { 905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferRange(instr); 906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Continue analysis in all dominated blocks. 910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < block->dominated_blocks()->length(); ++i) { 911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Analyze(block->dominated_blocks()->at(i)); 912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RollBackTo(last_changed_range); 915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 9181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid HRangeAnalysis::InferControlFlowRange(HTest* test, HBasicBlock* dest) { 9191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT((test->FirstSuccessor() == dest) == (test->SecondSuccessor() != dest)); 9201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (test->value()->IsCompare()) { 9211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HCompare* compare = HCompare::cast(test->value()); 92244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (compare->GetInputRepresentation().IsInteger32()) { 92344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Token::Value op = compare->token(); 92444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (test->SecondSuccessor() == dest) { 92544f0eee88ff00398ff7f715fab053374d808c90dSteve Block op = Token::NegateCompareOp(op); 92644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 92744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Token::Value inverted_op = Token::InvertCompareOp(op); 92844f0eee88ff00398ff7f715fab053374d808c90dSteve Block InferControlFlowRange(op, compare->left(), compare->right()); 92944f0eee88ff00398ff7f715fab053374d808c90dSteve Block InferControlFlowRange(inverted_op, compare->right(), compare->left()); 930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// We know that value [op] other. Use this information to update the range on 936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// value. 937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferControlFlowRange(Token::Value op, 938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* other) { 940e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Range temp_range; 941e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Range* range = other->range() != NULL ? other->range() : &temp_range; 942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* new_range = NULL; 943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Control flow range infer %d %s %d\n", 945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->id(), 946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Name(op), 947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->id()); 948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::EQ || op == Token::EQ_STRICT) { 950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The same range has to apply for value. 951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range = range->Copy(); 952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::LT || op == Token::LTE) { 953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range = range->CopyClearLower(); 954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::LT) { 955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->AddConstant(-1); 956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::GT || op == Token::GTE) { 958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range = range->CopyClearUpper(); 959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::GT) { 960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->AddConstant(1); 961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (new_range != NULL && !new_range->IsMostGeneric()) { 965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddRange(value, new_range); 966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferPhiRange(HPhi* phi) { 971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(twuerthinger): Infer loop phi ranges. 972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferRange(phi); 973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferRange(HValue* value) { 977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!value->HasRange()); 978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!value->representation().IsNone()) { 979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->ComputeInitialRange(); 980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* range = value->range(); 981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n", 982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->id(), 983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->Mnemonic(), 984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->lower(), 985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->upper()); 986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::RollBackTo(int index) { 991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = index + 1; i < changed_ranges_.length(); ++i) { 992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch changed_ranges_[i]->RemoveLastAddedRange(); 993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch changed_ranges_.Rewind(index + 1); 995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::AddRange(HValue* value, Range* range) { 999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* original_range = value->range(); 1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->AddNewRange(range); 1001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch changed_ranges_.Add(value); 1002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* new_range = value->range(); 1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Updated range of %d set to [%d,%d]\n", 1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->id(), 1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->lower(), 1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->upper()); 1007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (original_range != NULL) { 1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Original range was [%d,%d]\n", 1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch original_range->lower(), 1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch original_range->upper()); 1011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("New information was [%d,%d]\n", 1013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->lower(), 1014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->upper()); 1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TraceGVN(const char* msg, ...) { 1019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_gvn) { 1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_list arguments; 1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_start(arguments, msg); 1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch OS::VPrint(msg, arguments); 1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_end(arguments); 1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValueMap::HValueMap(const HValueMap* other) 1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : array_size_(other->array_size_), 1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_size_(other->lists_size_), 1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_(other->count_), 1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch present_flags_(other->present_flags_), 103344f0eee88ff00398ff7f715fab053374d808c90dSteve Block array_(ZONE->NewArray<HValueMapListElement>(other->array_size_)), 103444f0eee88ff00398ff7f715fab053374d808c90dSteve Block lists_(ZONE->NewArray<HValueMapListElement>(other->lists_size_)), 1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_(other->free_list_head_) { 1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement)); 1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement)); 1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Kill(int flags) { 1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int depends_flags = HValue::ConvertChangesToDependsFlags(flags); 1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ((present_flags_ & depends_flags) == 0) return; 1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch present_flags_ = 0; 1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < array_size_; ++i) { 1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = array_[i].value; 1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != NULL) { 1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Clear list of collisions first, so we know if it becomes empty. 1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int kept = kNil; // List of kept elements. 1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next; 1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int current = array_[i].next; current != kNil; current = next) { 1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next = lists_[current].next; 1053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ((lists_[current].value->flags() & depends_flags) != 0) { 1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop it. 1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_--; 1056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[current].next = free_list_head_; 1057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = current; 1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keep it. 1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[current].next = kept; 1061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch kept = current; 1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch present_flags_ |= lists_[current].value->flags(); 1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].next = kept; 1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Now possibly drop directly indexed element. 1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ((array_[i].value->flags() & depends_flags) != 0) { // Drop it. 1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_--; 1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int head = array_[i].next; 1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (head == kNil) { 1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].value = NULL; 1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].value = lists_[head].value; 1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].next = lists_[head].next; 1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[head].next = free_list_head_; 1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = head; 1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch present_flags_ |= array_[i].value->flags(); // Keep it. 1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValue* HValueMap::Lookup(HValue* value) const { 1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t hash = static_cast<uint32_t>(value->Hashcode()); 1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t pos = Bound(hash); 1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (array_[pos].value != NULL) { 1091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (array_[pos].value->Equals(value)) return array_[pos].value; 1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next = array_[pos].next; 1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (next != kNil) { 1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lists_[next].value->Equals(value)) return lists_[next].value; 1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next = lists_[next].next; 1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return NULL; 1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Resize(int new_size) { 1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(new_size > count_); 1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Hashing the values into the new array has no more collisions than in the 1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // old hash map, so we can use the existing lists_ array, if we are careful. 1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Make sure we have at least one free element. 1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (free_list_head_ == kNil) { 1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ResizeLists(lists_size_ << 1); 1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* new_array = 111344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZONE->NewArray<HValueMapListElement>(new_size); 1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memset(new_array, 0, sizeof(HValueMapListElement) * new_size); 1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* old_array = array_; 1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int old_size = array_size_; 1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int old_count = count_; 1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_ = 0; 1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do not modify present_flags_. It is currently correct. 1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_size_ = new_size; 1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_ = new_array; 1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (old_array != NULL) { 1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Iterate over all the elements in lists, rehashing them. 1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < old_size; ++i) { 1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (old_array[i].value != NULL) { 1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int current = old_array[i].next; 1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != kNil) { 1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Insert(lists_[current].value); 1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next = lists_[current].next; 1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[current].next = free_list_head_; 1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = current; 1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = next; 1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Rehash the directly stored value. 1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Insert(old_array[i].value); 1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch USE(old_count); 1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(count_ == old_count); 1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::ResizeLists(int new_size) { 1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(new_size > lists_size_); 1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* new_lists = 115144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZONE->NewArray<HValueMapListElement>(new_size); 1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memset(new_lists, 0, sizeof(HValueMapListElement) * new_size); 1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* old_lists = lists_; 1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int old_size = lists_size_; 1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_size_ = new_size; 1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_ = new_lists; 1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (old_lists != NULL) { 1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(lists_, old_lists, old_size * sizeof(HValueMapListElement)); 1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = old_size; i < lists_size_; ++i) { 1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[i].next = free_list_head_; 1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = i; 1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Insert(HValue* value) { 1171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(value != NULL); 1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Resizing when half of the hashtable is filled up. 1173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (count_ >= array_size_ >> 1) Resize(array_size_ << 1); 1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(count_ < array_size_); 1175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_++; 1176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t pos = Bound(static_cast<uint32_t>(value->Hashcode())); 1177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (array_[pos].value == NULL) { 1178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[pos].value = value; 1179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[pos].next = kNil; 1180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (free_list_head_ == kNil) { 1182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ResizeLists(lists_size_ << 1); 1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int new_element_pos = free_list_head_; 1185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(new_element_pos != kNil); 1186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = lists_[free_list_head_].next; 1187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[new_element_pos].value = value; 1188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[new_element_pos].next = array_[pos].next; 1189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL); 1190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[pos].next = new_element_pos; 1191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HStackCheckEliminator BASE_EMBEDDED { 1196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 1197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } 1198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Process(); 1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void RemoveStackCheck(HBasicBlock* block); 1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::Process() { 1209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For each loop block walk the dominator tree from the backwards branch to 1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the loop header. If a call instruction is encountered the backwards branch 1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // is dominated by a call and the stack check in the backwards branch can be 1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // removed. 1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < graph_->blocks()->length(); i++) { 1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge(); 1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dominator = back_edge; 1218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool back_edge_dominated_by_call = false; 1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (dominator != block && !back_edge_dominated_by_call) { 1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = dominator->first(); 1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL && !back_edge_dominated_by_call) { 1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->IsCall()) { 1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RemoveStackCheck(back_edge); 1224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch back_edge_dominated_by_call = true; 1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator = dominator->dominator(); 1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::RemoveStackCheck(HBasicBlock* block) { 1236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->IsGoto()) { 1239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGoto::cast(instr)->set_include_stack_check(false); 1240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 1241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 1243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HGlobalValueNumberer BASE_EMBEDDED { 1248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 1249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch explicit HGlobalValueNumberer(HGraph* graph, CompilationInfo* info) 1250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : graph_(graph), 1251e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch info_(info), 1252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block_side_effects_(graph_->blocks()->length()), 1253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_side_effects_(graph_->blocks()->length()) { 125444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(info->isolate()->heap()->allow_allocation(false)); 1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block_side_effects_.AddBlock(0, graph_->blocks()->length()); 1256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_side_effects_.AddBlock(0, graph_->blocks()->length()); 1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ~HGlobalValueNumberer() { 125944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!info_->isolate()->heap()->allow_allocation(true)); 1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(); 1263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AnalyzeBlock(HBasicBlock* block, HValueMap* map); 1266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void ComputeBlockSideEffects(); 1267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void LoopInvariantCodeMotion(); 1268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void ProcessLoopBlock(HBasicBlock* block, 1269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* before_loop, 1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int loop_kills); 1271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bool AllowCodeMotion(); 1272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); 1273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HGraph* graph() { return graph_; } 1275e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CompilationInfo* info() { return info_; } 12768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Zone* zone() { return graph_->zone(); } 1277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 1279e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CompilationInfo* info_; 1280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A map of block IDs to their side effects. 1282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<int> block_side_effects_; 1283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A map of loop header block IDs to their loop's side effects. 1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<int> loop_side_effects_; 1286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::Analyze() { 1290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ComputeBlockSideEffects(); 1291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_loop_invariant_code_motion) { 1292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LoopInvariantCodeMotion(); 1293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 12948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValueMap* map = new(zone()) HValueMap(); 1295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AnalyzeBlock(graph_->blocks()->at(0), map); 1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ComputeBlockSideEffects() { 1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute side effects for the block. 1302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int id = block->block_id(); 1305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int side_effects = 0; 1306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch side_effects |= (instr->flags() & HValue::ChangesFlagsMask()); 1308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 1309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block_side_effects_[id] |= side_effects; 1311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Loop headers are part of their loop. 1313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_side_effects_[id] |= side_effects; 1315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Propagate loop side effects upwards. 1318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->HasParentLoopHeader()) { 1319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int header_id = block->parent_loop_header()->block_id(); 1320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_side_effects_[header_id] |= 1321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->IsLoopHeader() ? loop_side_effects_[id] : side_effects; 1322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::LoopInvariantCodeMotion() { 1328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int side_effects = loop_side_effects_[block->block_id()]; 1332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", 1333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->block_id(), 1334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch side_effects); 1335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* last = block->loop_information()->GetLastBackEdge(); 1337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = block->block_id(); j <= last->block_id(); ++j) { 1338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects); 1339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block, 1346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header, 1347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int loop_kills) { 1348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* pre_header = loop_header->predecessors()->at(0); 1349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); 1350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", 1351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->block_id(), 1352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch depends_flags); 1353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* next = instr->next(); 1356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->CheckFlag(HValue::kUseGVN) && 1357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (instr->flags() & depends_flags) == 0) { 1358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Checking instruction %d (%s)\n", 1359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->id(), 1360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->Mnemonic()); 1361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool inputs_loop_invariant = true; 1362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < instr->OperandCount(); ++i) { 1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { 1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inputs_loop_invariant = false; 1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { 1369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Found loop invariant instruction %d\n", instr->id()); 1370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Move the instruction out of the loop. 1371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->Unlink(); 1372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->InsertBefore(pre_header->end()); 1373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = next; 1376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 13791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1380e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool HGlobalValueNumberer::AllowCodeMotion() { 1381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return info()->shared_info()->opt_count() + 1 < Compiler::kDefaultMaxOptCount; 1382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 1383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1384e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGlobalValueNumberer::ShouldMove(HInstruction* instr, 1386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header) { 13871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If we've disabled code motion, don't move any instructions. 1388e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!AllowCodeMotion()) return false; 13891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // If --aggressive-loop-invariant-motion, move everything except change 13911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // instructions. 13921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (FLAG_aggressive_loop_invariant_motion && !instr->IsChange()) { 1393b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch return true; 1394b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 13951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 13961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Otherwise only move instructions that postdominate the loop header 13971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // (i.e. are always executed inside the loop). This is to avoid 13981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // unnecessary deoptimizations assuming the loop is executed at least 13991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // once. TODO(fschneider): Better type feedback should give us 14001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // information about code that was never executed. 1401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = instr->block(); 1402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool result = true; 1403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block != loop_header) { 1404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 1; i < loop_header->predecessors()->length(); ++i) { 1405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool found = false; 1406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* pred = loop_header->predecessors()->at(i); 1407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (pred != loop_header) { 1408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (pred == block) found = true; 1409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pred = pred->dominator(); 1410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!found) { 1412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = false; 1413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { 1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Analyzing block B%d\n", block->block_id()); 1423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If this is a loop header kill everything killed by the loop. 1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->Kill(loop_side_effects_[block->block_id()]); 1427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Go through all instructions of the current block. 1430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* next = instr->next(); 1433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int flags = (instr->flags() & HValue::ChangesFlagsMask()); 1434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (flags != 0) { 1435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!instr->CheckFlag(HValue::kUseGVN)); 1436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Clear all instructions in the map that are affected by side effects. 1437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->Kill(flags); 1438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Instruction %d kills\n", instr->id()); 1439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (instr->CheckFlag(HValue::kUseGVN)) { 1440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* other = map->Lookup(instr); 1441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (other != NULL) { 1442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(instr->Equals(other) && other->Equals(instr)); 1443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Replacing value %d (%s) with value %d (%s)\n", 1444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->id(), 1445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->Mnemonic(), 1446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->id(), 1447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->Mnemonic()); 1448e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch instr->ReplaceAndDelete(other); 1449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->Add(instr); 1451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = next; 1454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Recursively continue analysis for all immediately dominated blocks. 1457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = block->dominated_blocks()->length(); 1458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; ++i) { 1459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dominated = block->dominated_blocks()->at(i); 1460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // No need to copy the map for the last child in the dominator tree. 14618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone()); 1462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the dominated block is not a successor to this block we have to 1464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // kill everything killed on any path between this block and the 1465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // dominated block. Note we rely on the block ordering. 1466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_successor = false; 1467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int predecessor_count = dominated->predecessors()->length(); 1468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; !is_successor && j < predecessor_count; ++j) { 1469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch is_successor = (dominated->predecessors()->at(j) == block); 1470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!is_successor) { 1473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int side_effects = 0; 1474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = block->block_id() + 1; j < dominated->block_id(); ++j) { 1475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch side_effects |= block_side_effects_[j]; 1476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch successor_map->Kill(side_effects); 1478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AnalyzeBlock(dominated, successor_map); 1481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HInferRepresentation BASE_EMBEDDED { 1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 1487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit HInferRepresentation(HGraph* graph) 1488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : graph_(graph), worklist_(8), in_worklist_(graph->GetMaximumValueID()) {} 1489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(); 1491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation TryChange(HValue* current); 1494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AddToWorklist(HValue* current); 1495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferBasedOnInputs(HValue* current); 1496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AddDependantsToWorklist(HValue* current); 1497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferBasedOnUses(HValue* current); 1498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 14998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Zone* zone() { return graph_->zone(); } 15008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 1501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 1502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> worklist_; 1503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector in_worklist_; 1504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddToWorklist(HValue* current) { 1508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->representation().IsSpecialization()) return; 1509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; 1510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (in_worklist_.Contains(current->id())) return; 1511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist_.Add(current); 1512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist_.Add(current->id()); 1513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method tries to specialize the representation type of the value 1517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as a parameter. The value is asked to infer its representation type 1518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// based on its inputs. If the inferred type is more specialized, then this 1519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// becomes the new representation type of the node. 1520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnInputs(HValue* current) { 1521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation r = current->representation(); 1522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (r.IsSpecialization()) return; 1523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); 1524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation inferred = current->InferredRepresentation(); 1525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (inferred.IsSpecialization()) { 1526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->ChangeRepresentation(inferred); 1527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddDependantsToWorklist(current); 1528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddDependantsToWorklist(HValue* current) { 1533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < current->uses()->length(); ++i) { 1534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToWorklist(current->uses()->at(i)); 1535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < current->OperandCount(); ++i) { 1537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToWorklist(current->OperandAt(i)); 1538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method calculates whether specializing the representation of the value 1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as the parameter has a benefit in terms of less necessary type 1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// conversions. If there is a benefit, then the representation of the value is 1545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// specialized. 1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnUses(HValue* current) { 1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation r = current->representation(); 1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (r.IsSpecialization() || current->HasNoUses()) return; 1549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); 1550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation new_rep = TryChange(current); 1551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!new_rep.IsNone()) { 1552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!current->representation().Equals(new_rep)) { 1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->ChangeRepresentation(new_rep); 1554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddDependantsToWorklist(current); 1555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HInferRepresentation::TryChange(HValue* current) { 1561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Array of use counts for each representation. 1562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int use_count[Representation::kNumRepresentations]; 1563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < Representation::kNumRepresentations; i++) { 1564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch use_count[i] = 0; 1565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < current->uses()->length(); ++i) { 1568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = current->uses()->at(i); 1569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = use->LookupOperandIndex(0, current); 1570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation req_rep = use->RequiredInputRepresentation(index); 1571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (req_rep.IsNone()) continue; 1572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (use->IsPhi()) { 1573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = HPhi::cast(use); 1574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddIndirectUsesTo(&use_count[0]); 1575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch use_count[req_rep.kind()]++; 1577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int tagged_count = use_count[Representation::kTagged]; 1579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int double_count = use_count[Representation::kDouble]; 1580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int int32_count = use_count[Representation::kInteger32]; 1581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int non_tagged_count = double_count + int32_count; 1582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If a non-loop phi has tagged uses, don't convert it to untagged. 1584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->IsPhi() && !current->block()->IsLoopHeader()) { 1585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (tagged_count > 0) return Representation::None(); 1586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (non_tagged_count >= tagged_count) { 1589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // More untagged than tagged. 1590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (double_count > 0) { 1591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is at least one usage that is a double => guess that the 1592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // correct representation is double. 1593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::Double(); 1594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (int32_count > 0) { 1595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::Integer32(); 1596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::None(); 1599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::Analyze() { 1603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Infer representations", graph_); 1604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // (1) Initialize bit vectors and count real uses. Each phi 1606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // gets a bit-vector of length <number of phis>. 1607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HPhi*>* phi_list = graph_->phi_list(); 1608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int num_phis = phi_list->length(); 1609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ScopedVector<BitVector*> connected_phis(num_phis); 1610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < num_phis; i++) { 1611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi_list->at(i)->InitRealUses(i); 16128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch connected_phis[i] = new(zone()) BitVector(num_phis); 1613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch connected_phis[i]->Add(i); 1614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // (2) Do a fixed point iteration to find the set of connected phis. 1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A phi is connected to another phi if its value is used either 1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // directly or indirectly through a transitive closure of the def-use 1619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // relation. 1620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool change = true; 1621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (change) { 1622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch change = false; 1623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < num_phis; i++) { 1624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list->at(i); 1625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < phi->uses()->length(); j++) { 1626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = phi->uses()->at(j); 1627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (use->IsPhi()) { 1628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int phi_use = HPhi::cast(use)->phi_id(); 1629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (connected_phis[i]->UnionIsChanged(*connected_phis[phi_use])) { 1630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch change = true; 1631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // (3) Sum up the non-phi use counts of all connected phis. 1638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Don't include the non-phi uses of the phi itself. 1639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < num_phis; i++) { 1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list->at(i); 1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (BitVector::Iterator it(connected_phis.at(i)); 1642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !it.Done(); 1643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch it.Advance()) { 1644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = it.Current(); 1645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (index != i) { 1646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* it_use = phi_list->at(it.Current()); 1647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddNonPhiUsesFrom(it_use); 1648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < graph_->blocks()->length(); ++i) { 1653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HPhi*>* phis = block->phis(); 1655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < phis->length(); ++j) { 1656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToWorklist(phis->at(j)); 1657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = block->first(); 1660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 1661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToWorklist(current); 1662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 1663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!worklist_.is_empty()) { 1667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* current = worklist_.RemoveLast(); 1668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist_.Remove(current->id()); 1669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferBasedOnInputs(current); 1670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferBasedOnUses(current); 1671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes() { 1676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Inferring types", this); 1677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InitializeInferredTypes(0, this->blocks_.length() - 1); 1678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) { 1682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = from_inclusive; i <= to_inclusive; ++i) { 1683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = blocks_[i]; 1684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HPhi*>* phis = block->phis(); 1686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < phis->length(); j++) { 1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis->at(j)->UpdateInferredType(); 1688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = block->first(); 1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 1692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->UpdateInferredType(); 1693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 1694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* last_back_edge = 1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->loop_information()->GetLastBackEdge(); 1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InitializeInferredTypes(i + 1, last_back_edge->block_id()); 1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Skip all blocks already processed by the recursive call. 1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch i = last_back_edge->block_id(); 1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Update phis of the loop header now after the whole loop body is 1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // guaranteed to be processed. 1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> worklist(block->phis()->length()); 1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < block->phis()->length(); ++j) { 1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist.Add(block->phis()->at(j)); 1707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferTypes(&worklist); 1709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) { 1715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* current = value; 1716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 1717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (visited->Contains(current->id())) return; 1718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For phis, we must propagate the check to all of its inputs. 1720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->IsPhi()) { 1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visited->Add(current->id()); 1722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = HPhi::cast(current); 1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phi->OperandCount(); ++i) { 1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(phi->OperandAt(i), visited); 1725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For multiplication and division, we must propagate to the left and 1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the right side. 1731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->IsMul()) { 1732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HMul* mul = HMul::cast(current); 1733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch mul->EnsureAndPropagateNotMinusZero(visited); 1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(mul->left(), visited); 1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(mul->right(), visited); 1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (current->IsDiv()) { 1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HDiv* div = HDiv::cast(current); 1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch div->EnsureAndPropagateNotMinusZero(visited); 1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(div->left(), visited); 1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(div->right(), visited); 1741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->EnsureAndPropagateNotMinusZero(visited); 1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChangeForUse(HValue* value, 1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use, 1750e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Representation to) { 1751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Insert the representation change right before its use. For phi-uses we 1752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // insert at the end of the corresponding predecessor. 17531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HInstruction* next = NULL; 1754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (use->IsPhi()) { 1755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = 0; 1756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (use->OperandAt(index) != value) ++index; 17571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block next = use->block()->predecessors()->at(index)->end(); 17581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 17591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block next = HInstruction::cast(use); 1760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For constants we try to make the representation change at compile 1763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // time. When a representation change is not possible without loss of 1764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // information we treat constants like normal instructions and insert the 1765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // change instructions for them. 1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* new_value = NULL; 1767e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32); 1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value->IsConstant()) { 1769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* constant = HConstant::cast(value); 1770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Try to create a new copy of the constant with the new representation. 1771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_value = is_truncating 1772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? constant->CopyToTruncatedInt32() 1773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : constant->CopyToRepresentation(to); 1774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (new_value == NULL) { 17778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new_value = 17788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HChange(value, value->representation(), to, is_truncating); 1779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_value->InsertBefore(next); 1782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->ReplaceFirstAtUse(use, new_value, to); 1783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint CompareConversionUses(HValue* a, 1787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* b, 1788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation a_rep, 1789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation b_rep) { 1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (a_rep.kind() > b_rep.kind()) { 1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Make sure specializations are separated in the result array. 1792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 1; 1793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Put truncating conversions before non-truncating conversions. 1795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool a_truncate = a->CheckFlag(HValue::kTruncatingToInt32); 1796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool b_truncate = b->CheckFlag(HValue::kTruncatingToInt32); 1797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (a_truncate != b_truncate) { 1798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return a_truncate ? -1 : 1; 1799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Sort by increasing block ID. 1801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return a->block()->block_id() - b->block()->block_id(); 1802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 180544f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HGraph::InsertRepresentationChangesForValue( 180644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* current, 180744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZoneList<HValue*>* to_convert, 180844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZoneList<Representation>* to_convert_reps) { 1809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation r = current->representation(); 1810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (r.IsNone()) return; 18118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (current->uses()->is_empty()) return; 1812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Collect the representation changes in a sorted list. This allows 1814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // us to avoid duplicate changes without searching the list. 181544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(to_convert->is_empty()); 181644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(to_convert_reps->is_empty()); 1817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < current->uses()->length(); ++i) { 1818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = current->uses()->at(i); 1819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The occurrences index means the index within the operand array of "use" 1820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // at which "current" is used. While iterating through the use array we 1821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // also have to iterate over the different occurrence indices. 1822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int occurrence_index = 0; 1823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (use->UsesMultipleTimes(current)) { 1824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1); 1825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_representation) { 1826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n", 1827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->id(), 1828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch use->id(), 1829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch occurrence_index); 1830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int operand_index = use->LookupOperandIndex(occurrence_index, current); 1833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation req = use->RequiredInputRepresentation(operand_index); 1834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (req.IsNone() || req.Equals(r)) continue; 1835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = 0; 183644f0eee88ff00398ff7f715fab053374d808c90dSteve Block while (index < to_convert->length() && 183744f0eee88ff00398ff7f715fab053374d808c90dSteve Block CompareConversionUses(to_convert->at(index), 1838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch use, 183944f0eee88ff00398ff7f715fab053374d808c90dSteve Block to_convert_reps->at(index), 1840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch req) < 0) { 1841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ++index; 1842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_representation) { 1844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Inserting a representation change to %s of %d for use at %d\n", 1845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch req.Mnemonic(), 1846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->id(), 1847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch use->id()); 1848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 184944f0eee88ff00398ff7f715fab053374d808c90dSteve Block to_convert->InsertAt(index, use); 185044f0eee88ff00398ff7f715fab053374d808c90dSteve Block to_convert_reps->InsertAt(index, req); 1851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 185344f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < to_convert->length(); ++i) { 185444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* use = to_convert->at(i); 185544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Representation r_to = to_convert_reps->at(i); 1856e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch InsertRepresentationChangeForUse(current, use, r_to); 1857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->uses()->is_empty()) { 1860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current->IsConstant()); 1861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->Delete(); 1862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 186344f0eee88ff00398ff7f715fab053374d808c90dSteve Block to_convert->Rewind(0); 186444f0eee88ff00398ff7f715fab053374d808c90dSteve Block to_convert_reps->Rewind(0); 1865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChanges() { 1869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Insert representation changes", this); 1870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute truncation flag for phis: Initially assume that all 1873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // int32-phis allow truncation and iteratively remove the ones that 1874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // are used in an operation that does not allow a truncating 1875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // conversion. 1876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(fschneider): Replace this with a worklist-based iteration. 1877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phi_list()->length(); i++) { 1878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list()->at(i); 1879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (phi->representation().IsInteger32()) { 1880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->SetFlag(HValue::kTruncatingToInt32); 1881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool change = true; 1884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (change) { 1885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch change = false; 1886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phi_list()->length(); i++) { 1887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list()->at(i); 1888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; 1889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < phi->uses()->length(); j++) { 1890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = phi->uses()->at(j); 1891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!use->CheckFlag(HValue::kTruncatingToInt32)) { 1892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->ClearFlag(HValue::kTruncatingToInt32); 1893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch change = true; 1894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 190044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZoneList<HValue*> value_list(4); 190144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZoneList<Representation> rep_list(4); 1902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 1903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Process phi instructions first. 1904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < blocks_[i]->phis()->length(); j++) { 1905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = blocks_[i]->phis()->at(j); 190644f0eee88ff00398ff7f715fab053374d808c90dSteve Block InsertRepresentationChangesForValue(phi, &value_list, &rep_list); 1907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Process normal instructions. 1910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = blocks_[i]->first(); 1911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 191244f0eee88ff00398ff7f715fab053374d808c90dSteve Block InsertRepresentationChangesForValue(current, &value_list, &rep_list); 1913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 1914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 19191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid HGraph::ComputeMinusZeroChecks() { 19201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block BitVector visited(GetMaximumValueID()); 19211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < blocks_.length(); ++i) { 19221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (HInstruction* current = blocks_[i]->first(); 19231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block current != NULL; 19241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block current = current->next()) { 19251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (current->IsChange()) { 19261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HChange* change = HChange::cast(current); 19271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Propagate flags for negative zero checks upwards from conversions 19281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // int32-to-tagged and int32-to-double. 19291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Representation from = change->value()->representation(); 19301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(from.Equals(change->from())); 19311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (from.IsInteger32()) { 19321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(change->to().IsTagged() || change->to().IsDouble()); 19331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(visited.IsEmpty()); 19341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PropagateMinusZeroChecks(change->value(), &visited); 19351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block visited.Clear(); 19361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 19371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 19381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 19391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 19401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 19411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 19421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 1943e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// Implementation of utility class to encapsulate the translation state for 1944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch// a (possibly inlined) function. 1945e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochFunctionState::FunctionState(HGraphBuilder* owner, 1946e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CompilationInfo* info, 1947e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TypeFeedbackOracle* oracle) 1948e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch : owner_(owner), 1949e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch compilation_info_(info), 1950e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch oracle_(oracle), 1951e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch call_context_(NULL), 1952e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch function_return_(NULL), 1953e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch test_context_(NULL), 1954e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch outer_(owner->function_state()) { 1955e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (outer_ != NULL) { 1956e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // State for an inline function. 1957e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (owner->ast_context()->IsTest()) { 1958e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_true = owner->graph()->CreateBasicBlock(); 1959e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_false = owner->graph()->CreateBasicBlock(); 1960e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if_true->MarkAsInlineReturnTarget(); 1961e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if_false->MarkAsInlineReturnTarget(); 1962e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The AstContext constructor pushed on the context stack. This newed 1963e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // instance is the reason that AstContext can't be BASE_EMBEDDED. 1964e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch test_context_ = new TestContext(owner, if_true, if_false); 1965e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 1966e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch function_return_ = owner->graph()->CreateBasicBlock(); 1967e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch function_return()->MarkAsInlineReturnTarget(); 1968e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1969e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Set this after possibly allocating a new TestContext above. 1970e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch call_context_ = owner->ast_context(); 1971e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 1972e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1973e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Push on the state stack. 1974e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch owner->set_function_state(this); 1975e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 1976e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1977e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1978e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochFunctionState::~FunctionState() { 1979e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch delete test_context_; 1980e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch owner_->set_function_state(outer_); 1981e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 1982e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1983e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 1984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Implementation of utility classes to represent an expression's context in 1985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the AST. 1986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) 19878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : owner_(owner), 19888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch kind_(kind), 19898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch outer_(owner->ast_context()), 19908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for_typeof_(false) { 1991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner->set_ast_context(this); // Push. 1992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 19939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block original_length_ = owner->environment()->length(); 1994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 1995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::~AstContext() { 1999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner_->set_ast_context(outer_); // Pop. 2000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochEffectContext::~EffectContext() { 2004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(owner()->HasStackOverflow() || 2005e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch owner()->current_block() == NULL || 20069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block owner()->environment()->length() == original_length_); 2007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochValueContext::~ValueContext() { 2011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(owner()->HasStackOverflow() || 2012e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch owner()->current_block() == NULL || 20139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block owner()->environment()->length() == original_length_ + 1); 2014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnValue(HValue* value) { 2018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The value is simply ignored. 2019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnValue(HValue* value) { 2023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The value is tracked in the bailout environment, and communicated 2024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // through the environment as the result of the expression. 2025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->Push(value); 2026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnValue(HValue* value) { 2030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildBranch(value); 2031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) { 2035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->AddInstruction(instr); 2036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); 2037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { 2041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->AddInstruction(instr); 2042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->Push(instr); 2043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); 2044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { 2048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder* builder = owner(); 2049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->AddInstruction(instr); 2050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We expect a simulate after every expression with side effects, though 2051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // this one isn't actually needed (and wouldn't work if it were targeted). 2052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) { 2053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->Push(instr); 2054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->AddSimulate(ast_id); 2055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->Pop(); 2056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildBranch(instr); 2058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::BuildBranch(HValue* value) { 2062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We expect the graph to be in edge-split form: there is no edge that 2063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // connects a branch node to a join node. We conservatively ensure that 2064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // property by always adding an empty block on the outgoing edges of this 2065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // branch. 2066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder* builder = owner(); 2067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 20698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HTest* test = new(zone()) HTest(value, empty_true, empty_false); 2070e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch builder->current_block()->Finish(test); 2071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 207244f0eee88ff00398ff7f715fab053374d808c90dSteve Block empty_true->Goto(if_true(), false); 207344f0eee88ff00398ff7f715fab053374d808c90dSteve Block empty_false->Goto(if_false(), false); 2074e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch builder->set_current_block(NULL); 2075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// HGraphBuilder infrastructure for bailing out and checking bailouts. 20798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#define CHECK_BAILOUT(call) \ 2080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { \ 20818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call; \ 2082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return; \ 2083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (false) 2084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 20868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#define CHECK_ALIVE(call) \ 2087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { \ 20888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call; \ 20898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return; \ 2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (false) 2091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::Bailout(const char* reason) { 2094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_bailout) { 2095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch SmartPointer<char> name(info()->shared_info()->DebugName()->ToCString()); 2096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *name, reason); 2097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetStackOverflow(); 2099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForEffect(Expression* expr) { 2103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EffectContext for_effect(this); 2104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr); 2105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForValue(Expression* expr) { 2109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ValueContext for_value(this); 2110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr); 2111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 21148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochvoid HGraphBuilder::VisitForTypeOf(Expression* expr) { 21158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ValueContext for_value(this); 21168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for_value.set_for_typeof(true); 21178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Visit(expr); 21188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 21198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 21208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 21218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 2122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForControl(Expression* expr, 2123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* true_block, 2124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* false_block) { 2125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestContext for_test(this, true_block, false_block); 2126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr); 2127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 21301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockvoid HGraphBuilder::VisitArgument(Expression* expr) { 21318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr)); 21328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Push(AddInstruction(new(zone()) HPushArgument(Pop()))); 2133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { 2137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < arguments->length(); i++) { 21388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgument(arguments->at(i))); 2139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs) { 2144e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < exprs->length(); ++i) { 21458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(exprs->at(i))); 2146e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2147e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2149e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2150e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHGraph* HGraphBuilder::CreateGraph() { 21518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch graph_ = new(zone()) HGraph(info()); 215244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_hydrogen_stats) HStatistics::Instance()->Initialize(info()); 2153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 2155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Block building"); 215644f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block_ = graph()->entry_block(); 2157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Scope* scope = info()->scope(); 2159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (scope->HasIllegalRedeclaration()) { 2160e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Bailout("function with illegal redeclaration"); 2161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return NULL; 2162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetupScope(scope); 2164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitDeclarations(scope->declarations()); 21658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HStackCheck()); 2166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Add an edge to the body entry. This is warty: the graph's start 2168e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // environment will be used by the Lithium translation as the initial 2169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // environment on graph entry, but it has now been mutated by the 2170e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Hydrogen translation of the instructions in the start block. This 2171e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // environment uses values which have not been defined yet. These 2172e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Hydrogen instructions will then be replayed by the Lithium 2173e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // translation, so they cannot have an environment effect. The edge to 2174e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // the body's entry block (along with some special logic for the start 2175e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // block in HInstruction::InsertAfter) seals the start block from 2176e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // getting unwanted instructions inserted. 2177e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // 2178e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(kmillikin): Fix this. Stop mutating the initial environment. 2179e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Make the Hydrogen instructions in the initial block into Hydrogen 2180e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // values (but not instructions), present in the initial environment and 2181e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // not replayed by the Lithium translation. 2182e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HEnvironment* initial_env = environment()->CopyWithoutHistory(); 2183e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_entry = CreateBasicBlock(initial_env); 2184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(body_entry); 21858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch body_entry->SetJoinId(AstNode::kFunctionEntryId); 2186e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(body_entry); 2187e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitStatements(info()->function()->body()); 2188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return NULL; 2189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2190e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (current_block() != NULL) { 21918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HReturn* instr = new(zone()) HReturn(graph()->GetConstantUndefined()); 2192e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->FinishExit(instr); 2193e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 2194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch graph()->OrderBlocks(); 2198e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch graph()->AssignDominators(); 2199e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch graph()->EliminateRedundantPhis(); 220044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_eliminate_dead_phis) graph()->EliminateUnreachablePhis(); 2201e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!graph()->CollectPhis()) { 2202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Bailout("Phi-use of arguments object"); 2203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return NULL; 2204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2206e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HInferRepresentation rep(graph()); 2207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch rep.Analyze(); 2208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_use_range) { 2210e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HRangeAnalysis rangeAnalysis(graph()); 2211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch rangeAnalysis.Analyze(); 2212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2214e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch graph()->InitializeInferredTypes(); 2215e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch graph()->Canonicalize(); 2216e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch graph()->InsertRepresentationChanges(); 2217e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch graph()->ComputeMinusZeroChecks(); 2218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Eliminate redundant stack checks on backwards branches. 2220e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HStackCheckEliminator sce(graph()); 2221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch sce.Process(); 2222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Perform common subexpression elimination and loop-invariant code motion. 2224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_use_gvn) { 2225e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HPhase phase("Global value numbering", graph()); 2226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HGlobalValueNumberer gvn(graph(), info()); 2227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch gvn.Analyze(); 2228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2230e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return graph(); 2231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 2235e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 2236e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->AddInstruction(instr); 2237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 2238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddSimulate(int id) { 2242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 2243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->AddSimulate(id); 2244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddPhi(HPhi* instr) { 2248e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 2249e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->AddPhi(instr); 2250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::PushAndAdd(HInstruction* instr) { 2254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(instr); 2255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 2256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochtemplate <int V> 2260e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHInstruction* HGraphBuilder::PreProcessCall(HCall<V>* call) { 22611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int count = call->argument_count(); 22621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ZoneList<HValue*> arguments(count); 22631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block for (int i = 0; i < count; ++i) { 22641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block arguments.Add(Pop()); 2265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block while (!arguments.is_empty()) { 22688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HPushArgument(arguments.RemoveLast())); 2269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2270e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return call; 2271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::SetupScope(Scope* scope) { 2275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't yet handle the function name for named function expressions. 22768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (scope->function() != NULL) return Bailout("named function expression"); 2277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HConstant* undefined_constant = new(zone()) HConstant( 227944f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()->factory()->undefined_value(), Representation::Tagged()); 2280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(undefined_constant); 2281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->set_undefined_constant(undefined_constant); 2282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Set the initial values of parameters including "this". "This" has 2284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // parameter index 0. 2285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int count = scope->num_parameters() + 1; 2286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < count; ++i) { 22878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* parameter = AddInstruction(new(zone()) HParameter(i)); 2288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->Bind(i, parameter); 2289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Set the initial values of stack-allocated locals. 22929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = count; i < environment()->length(); ++i) { 2293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->Bind(i, undefined_constant); 2294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Handle the arguments and arguments shadow variables specially (they do 2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // not have declarations). 2298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (scope->arguments() != NULL) { 2299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!scope->arguments()->IsStackAllocated() || 230044f0eee88ff00398ff7f715fab053374d808c90dSteve Block (scope->arguments_shadow() != NULL && 230144f0eee88ff00398ff7f715fab053374d808c90dSteve Block !scope->arguments_shadow()->IsStackAllocated())) { 23028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("context-allocated arguments"); 2303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 23048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HArgumentsObject* object = new(zone()) HArgumentsObject; 2305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(object); 2306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph()->SetArgumentsObject(object); 2307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->Bind(scope->arguments(), object); 230844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (scope->arguments_shadow() != NULL) { 230944f0eee88ff00398ff7f715fab053374d808c90dSteve Block environment()->Bind(scope->arguments_shadow(), object); 231044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { 2316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < statements->length(); i++) { 23178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(Visit(statements->at(i))); 2318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 2323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* b = graph()->CreateBasicBlock(); 2324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch b->SetInitialEnvironment(env); 2325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return b; 2326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() { 2330e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* header = graph()->CreateBasicBlock(); 2331e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HEnvironment* entry_env = environment()->CopyAsLoopHeader(header); 2332e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch header->SetInitialEnvironment(entry_env); 2333e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch header->AttachLoopInformation(); 2334e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return header; 2335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBlock(Block* stmt) { 23398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 23408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 23418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2342e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueInfo break_info(stmt); 2343e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { BreakAndContinueScope push(&break_info, this); 23448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitStatements(stmt->statements())); 2345e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2346e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* break_block = break_info.break_block(); 2347e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (break_block != NULL) { 2348e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (current_block() != NULL) current_block()->Goto(break_block); 2349e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break_block->SetJoinId(stmt->ExitId()); 2350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(break_block); 2351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { 23568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 23578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 23588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForEffect(stmt->expression()); 2360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { 23648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 23658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 23668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitIfStatement(IfStatement* stmt) { 23718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 23728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 23738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt->condition()->ToBooleanIsTrue()) { 2375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(stmt->ThenId()); 2376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(stmt->then_statement()); 2377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (stmt->condition()->ToBooleanIsFalse()) { 2378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(stmt->ElseId()); 2379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(stmt->else_statement()); 2380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* cond_true = graph()->CreateBasicBlock(); 2382e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* cond_false = graph()->CreateBasicBlock(); 23838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false)); 2384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 23858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (cond_true->HasPredecessor()) { 23868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_true->SetJoinId(stmt->ThenId()); 23878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(cond_true); 23888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(Visit(stmt->then_statement())); 23898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_true = current_block(); 23908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 23918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_true = NULL; 23928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 23948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (cond_false->HasPredecessor()) { 23958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_false->SetJoinId(stmt->ElseId()); 23968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(cond_false); 23978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(Visit(stmt->else_statement())); 23988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_false = current_block(); 23998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 24008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_false = NULL; 24018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 24038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->id()); 2404e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(join); 2405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2409e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen MurdochHBasicBlock* HGraphBuilder::BreakAndContinueScope::Get( 2410e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakableStatement* stmt, 2411e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakType type) { 2412e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueScope* current = this; 2413e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (current != NULL && current->info()->target() != stmt) { 2414e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current = current->next(); 2415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2416e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current != NULL); // Always found (unless stack is malformed). 2417e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* block = NULL; 2418e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch switch (type) { 2419e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case BREAK: 2420e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch block = current->info()->break_block(); 2421e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (block == NULL) { 2422e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch block = current->owner()->graph()->CreateBasicBlock(); 2423e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current->info()->set_break_block(block); 2424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2425e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2426e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2427e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch case CONTINUE: 2428e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch block = current->info()->continue_block(); 2429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (block == NULL) { 2430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch block = current->owner()->graph()->CreateBasicBlock(); 2431e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current->info()->set_continue_block(block); 2432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break; 2434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2435e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return block; 2437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { 24418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 24428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 24438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2444e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* continue_block = break_scope()->Get(stmt->target(), CONTINUE); 2445e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(continue_block); 2446e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 2447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { 24518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 24528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 24538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* break_block = break_scope()->Get(stmt->target(), BREAK); 2455e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(break_block); 2456e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 2457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 24618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 24628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 24638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AstContext* context = call_context(); 2465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (context == NULL) { 2466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Not an inlined return, so an actual one. 24678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(stmt->expression())); 2468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* result = environment()->Pop(); 24698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch current_block()->FinishExit(new(zone()) HReturn(result)); 2470e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 2471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return from an inlined function, visit the subexpression in the 2473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // expression context of the call. 2474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (context->IsTest()) { 2475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestContext* test = TestContext::cast(context); 2476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForControl(stmt->expression(), 2477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch test->if_true(), 2478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch test->if_false()); 247944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (context->IsEffect()) { 24808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForEffect(stmt->expression())); 248144f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->Goto(function_return(), false); 2482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 248344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(context->IsValue()); 24848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(stmt->expression())); 248544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* return_value = environment()->Pop(); 248644f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->AddLeaveInlined(return_value, function_return()); 2487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 248844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(NULL); 2489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 24948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 24958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 24968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 24978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("WithEnterStatement"); 2498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { 25028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 25038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 25048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 25058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("WithExitStatement"); 2506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 25108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 25118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 25128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 251344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We only optimize switch statements with smi-literal smi comparisons, 251444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // with a bounded number of clauses. 251544f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int kCaseClauseLimit = 128; 251644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ZoneList<CaseClause*>* clauses = stmt->cases(); 251744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int clause_count = clauses->length(); 251844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (clause_count > kCaseClauseLimit) { 25198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("SwitchStatement: too many clauses"); 252044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 252144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 25228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(stmt->tag())); 2523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(stmt->EntryId()); 252444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* tag_value = Pop(); 252544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* first_test_block = current_block(); 2526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 252744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // 1. Build all the tests, with dangling true branches. Unconditionally 252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // deoptimize if we encounter a non-smi comparison. 252944f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < clause_count; ++i) { 2530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CaseClause* clause = clauses->at(i); 2531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (clause->is_default()) continue; 2532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!clause->label()->IsSmiLiteral()) { 25338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("SwitchStatement: non-literal switch label"); 2534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 253644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Unconditionally deoptimize on the first non-smi compare. 253744f0eee88ff00398ff7f715fab053374d808c90dSteve Block clause->RecordTypeFeedback(oracle()); 253844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!clause->IsSmiCompare()) { 253944f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->FinishExitWithDeoptimization(); 254044f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(NULL); 254144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 2542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 254444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Otherwise generate a compare and branch. 25458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(clause->label())); 254644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* label_value = Pop(); 25478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCompare* compare = 25488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCompare(tag_value, label_value, Token::EQ_STRICT); 254944f0eee88ff00398ff7f715fab053374d808c90dSteve Block compare->SetInputRepresentation(Representation::Integer32()); 255044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(!compare->HasSideEffects()); 255144f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(compare); 255244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* body_block = graph()->CreateBasicBlock(); 255344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* next_test_block = graph()->CreateBasicBlock(); 25548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HTest* branch = new(zone()) HTest(compare, body_block, next_test_block); 255544f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->Finish(branch); 255644f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(next_test_block); 255744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 255844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 255944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Save the current block to use for the default or to join with the 256044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // exit. This block is NULL if we deoptimized. 256144f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* last_block = current_block(); 256244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 256344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // 2. Loop over the clauses and the linked list of tests in lockstep, 256444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // translating the clause bodies. 256544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* curr_test_block = first_test_block; 256644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* fall_through_block = NULL; 256744f0eee88ff00398ff7f715fab053374d808c90dSteve Block BreakAndContinueInfo break_info(stmt); 256844f0eee88ff00398ff7f715fab053374d808c90dSteve Block { BreakAndContinueScope push(&break_info, this); 256944f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < clause_count; ++i) { 257044f0eee88ff00398ff7f715fab053374d808c90dSteve Block CaseClause* clause = clauses->at(i); 257144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 257244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Identify the block where normal (non-fall-through) control flow 257344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // goes to. 257444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* normal_block = NULL; 257544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (clause->is_default() && last_block != NULL) { 257644f0eee88ff00398ff7f715fab053374d808c90dSteve Block normal_block = last_block; 257744f0eee88ff00398ff7f715fab053374d808c90dSteve Block last_block = NULL; // Cleared to indicate we've handled it. 257844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (!curr_test_block->end()->IsDeoptimize()) { 257944f0eee88ff00398ff7f715fab053374d808c90dSteve Block normal_block = curr_test_block->end()->FirstSuccessor(); 258044f0eee88ff00398ff7f715fab053374d808c90dSteve Block curr_test_block = curr_test_block->end()->SecondSuccessor(); 258144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 258344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Identify a block to emit the body into. 258444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (normal_block == NULL) { 258544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (fall_through_block == NULL) { 258644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (a) Unreachable. 258744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (clause->is_default()) { 258844f0eee88ff00398ff7f715fab053374d808c90dSteve Block continue; // Might still be reachable clause bodies. 258944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 259044f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 259144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 259244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 259344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (b) Reachable only as fall through. 259444f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(fall_through_block); 2595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 259644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (fall_through_block == NULL) { 259744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (c) Reachable only normally. 259844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(normal_block); 2599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 260044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (d) Reachable both ways. 260144f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* join = CreateJoin(fall_through_block, 260244f0eee88ff00398ff7f715fab053374d808c90dSteve Block normal_block, 260344f0eee88ff00398ff7f715fab053374d808c90dSteve Block clause->EntryId()); 260444f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(join); 2605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 26078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitStatements(clause->statements())); 260844f0eee88ff00398ff7f715fab053374d808c90dSteve Block fall_through_block = current_block(); 2609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 261244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Create an up-to-3-way join. Use the break block if it exists since 261344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // it's already a join block. 261444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* break_block = break_info.break_block(); 261544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (break_block == NULL) { 261644f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(CreateJoin(fall_through_block, 261744f0eee88ff00398ff7f715fab053374d808c90dSteve Block last_block, 261844f0eee88ff00398ff7f715fab053374d808c90dSteve Block stmt->ExitId())); 2619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 262044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (fall_through_block != NULL) fall_through_block->Goto(break_block); 262144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (last_block != NULL) last_block->Goto(break_block); 262244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break_block->SetJoinId(stmt->ExitId()); 262344f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(break_block); 2624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 262744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 2628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochbool HGraphBuilder::HasOsrEntryAt(IterationStatement* statement) { 2629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return statement->OsrEntryId() == info()->osr_ast_id(); 2630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2633e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::PreProcessOsrEntry(IterationStatement* statement) { 2634e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!HasOsrEntryAt(statement)) return; 2635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); 2637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* osr_entry = graph()->CreateBasicBlock(); 2638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* true_value = graph()->GetConstantTrue(); 26398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HTest* test = new(zone()) HTest(true_value, non_osr_entry, osr_entry); 2640e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Finish(test); 2641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); 2643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch non_osr_entry->Goto(loop_predecessor); 2644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2645e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(osr_entry); 2646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int osr_entry_id = statement->OsrEntryId(); 2647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We want the correct environment at the OsrEntry instruction. Build 2648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // it explicitly. The expression stack should be empty. 2649e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int count = environment()->length(); 2650e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(count == 2651e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (environment()->parameter_count() + environment()->local_count())); 2652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < count; ++i) { 26538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HUnknownOSRValue* unknown = new(zone()) HUnknownOSRValue; 2654e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddInstruction(unknown); 2655e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch environment()->Bind(i, unknown); 2656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2658e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddSimulate(osr_entry_id); 26598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HOsrEntry(osr_entry_id)); 2660e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(loop_predecessor); 2661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_predecessor->SetJoinId(statement->EntryId()); 2662e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_predecessor); 2663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 26678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 26688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 26698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2670e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 2671e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PreProcessOsrEntry(stmt); 2672e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 2673e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(loop_entry, false); 2674e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_entry); 2675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueInfo break_info(stmt); 2677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch { BreakAndContinueScope push(&break_info, this); 26788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(Visit(stmt->body())); 2679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2680e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_exit = 2681e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch JoinContinue(stmt, current_block(), break_info.continue_block()); 2682e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_successor = NULL; 2683e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) { 2684e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(body_exit); 2685e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The block for a true condition, the actual predecessor block of the 2686e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // back edge. 2687e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch body_exit = graph()->CreateBasicBlock(); 2688e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor = graph()->CreateBasicBlock(); 26898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor)); 26908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (body_exit->HasPredecessor()) { 26918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch body_exit->SetJoinId(stmt->BackEdgeId()); 26928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 26938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch body_exit = NULL; 26948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 26958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (loop_successor->HasPredecessor()) { 26968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch loop_successor->SetJoinId(stmt->ExitId()); 26978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 26988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch loop_successor = NULL; 26998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_exit = CreateLoop(stmt, 2702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_entry, 2703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch body_exit, 2704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor, 2705e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break_info.break_block()); 2706e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_exit); 2707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2710e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { 27118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 27128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 27138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2714e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 2715e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PreProcessOsrEntry(stmt); 2716e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 2717e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(loop_entry, false); 2718e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_entry); 2719e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2720e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // If the condition is constant true, do not generate a branch. 2721e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_successor = NULL; 2722e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!stmt->cond()->ToBooleanIsTrue()) { 2723e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_entry = graph()->CreateBasicBlock(); 2724e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor = graph()->CreateBasicBlock(); 27258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); 27268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (body_entry->HasPredecessor()) { 27278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch body_entry->SetJoinId(stmt->BodyId()); 27288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(body_entry); 27298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 27308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (loop_successor->HasPredecessor()) { 27318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch loop_successor->SetJoinId(stmt->ExitId()); 27328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 27338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch loop_successor = NULL; 27348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2735e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 2736e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2737e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueInfo break_info(stmt); 27388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (current_block() != NULL) { 27398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch BreakAndContinueScope push(&break_info, this); 27408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(Visit(stmt->body())); 2741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2742e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_exit = 2743e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch JoinContinue(stmt, current_block(), break_info.continue_block()); 2744e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_exit = CreateLoop(stmt, 2745e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_entry, 2746e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch body_exit, 2747e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor, 2748e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break_info.break_block()); 2749e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_exit); 2750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForStatement(ForStatement* stmt) { 27548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 27558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 27568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2757e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (stmt->init() != NULL) { 27588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(Visit(stmt->init())); 2759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2760e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 2761e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PreProcessOsrEntry(stmt); 2762e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_entry = CreateLoopHeaderBlock(); 2763e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(loop_entry, false); 2764e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_entry); 2765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2766e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_successor = NULL; 2767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt->cond() != NULL) { 2768e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_entry = graph()->CreateBasicBlock(); 2769e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor = graph()->CreateBasicBlock(); 27708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor)); 27718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (body_entry->HasPredecessor()) { 27728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch body_entry->SetJoinId(stmt->BodyId()); 27738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(body_entry); 27748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 27758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (loop_successor->HasPredecessor()) { 27768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch loop_successor->SetJoinId(stmt->ExitId()); 27778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 27788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch loop_successor = NULL; 27798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2782e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch BreakAndContinueInfo break_info(stmt); 27838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (current_block() != NULL) { 27848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch BreakAndContinueScope push(&break_info, this); 27858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(Visit(stmt->body())); 2786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* body_exit = 2788e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch JoinContinue(stmt, current_block(), break_info.continue_block()); 2789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2790e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (stmt->next() != NULL && body_exit != NULL) { 2791e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(body_exit); 27928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(Visit(stmt->next())); 2793e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch body_exit = current_block(); 2794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2795e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2796e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* loop_exit = CreateLoop(stmt, 2797e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_entry, 2798e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch body_exit, 2799e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch loop_successor, 2800e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch break_info.break_block()); 2801e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(loop_exit); 2802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { 28068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 28078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 28088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 28098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("ForInStatement"); 2810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 28148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 28158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 28168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 28178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("TryCatchStatement"); 2818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 28228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 28238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 28248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 28258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("TryFinallyStatement"); 2826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 28308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 28318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 28328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 28338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("DebuggerStatement"); 28348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 28358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 28368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 28378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdochstatic Handle<SharedFunctionInfo> SearchSharedFunctionInfo( 28388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Code* unoptimized_code, FunctionLiteral* expr) { 28398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int start_position = expr->start_position(); 28408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocIterator it(unoptimized_code); 28418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (;!it.done(); it.next()) { 28428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch RelocInfo* rinfo = it.rinfo(); 28438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (rinfo->rmode() != RelocInfo::EMBEDDED_OBJECT) continue; 28448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Object* obj = rinfo->target_object(); 28458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (obj->IsSharedFunctionInfo()) { 28468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); 28478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (shared->start_position() == start_position) { 28488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Handle<SharedFunctionInfo>(shared); 28498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 28508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 28518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 28528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 28538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Handle<SharedFunctionInfo>(); 2854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 28588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 28598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 28608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<SharedFunctionInfo> shared_info = 28628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SearchSharedFunctionInfo(info()->shared_info()->code(), 28638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr); 28648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (shared_info.is_null()) { 28658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch shared_info = Compiler::BuildFunctionInfo(expr, info()->script()); 28668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 28678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // We also have a stack overflow if the recursive compilation did. 28688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (HasStackOverflow()) return; 2869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HFunctionLiteral* instr = 28708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HFunctionLiteral(shared_info, expr->pretenure()); 2871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 2872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSharedFunctionInfoLiteral( 2876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SharedFunctionInfoLiteral* expr) { 28778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 28788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 28798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 28808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("SharedFunctionInfoLiteral"); 2881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitConditional(Conditional* expr) { 28858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 28868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 28878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2888e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* cond_true = graph()->CreateBasicBlock(); 2889e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* cond_false = graph()->CreateBasicBlock(); 28908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false)); 2891e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 289244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Visit the true and false subexpressions in the same AST context as the 289344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // whole expression. 28948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (cond_true->HasPredecessor()) { 28958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_true->SetJoinId(expr->ThenId()); 28968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(cond_true); 28978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(Visit(expr->then_expression())); 28988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_true = current_block(); 28998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 29008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_true = NULL; 29018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2902e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 29038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (cond_false->HasPredecessor()) { 29048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_false->SetJoinId(expr->ElseId()); 29058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(cond_false); 29068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(Visit(expr->else_expression())); 29078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_false = current_block(); 29088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 29098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch cond_false = NULL; 29108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 2911e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 291244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!ast_context()->IsTest()) { 29138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id()); 291444f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(join); 29158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (join != NULL && !ast_context()->IsEffect()) { 29168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ast_context()->ReturnValue(Pop()); 29178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 291844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 2919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 29228b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochHGraphBuilder::GlobalPropertyAccess HGraphBuilder::LookupGlobalProperty( 29238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Variable* var, LookupResult* lookup, bool is_store) { 29248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (var->is_this() || !info()->has_global_object()) { 29258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return kUseGeneric; 2926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2927e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<GlobalObject> global(info()->global_object()); 2928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch global->Lookup(*var->name(), lookup); 29298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!lookup->IsProperty() || 29308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch lookup->type() != NORMAL || 29318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch (is_store && lookup->IsReadOnly()) || 29328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch lookup->holder() != *global) { 29338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return kUseGeneric; 29341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 29358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 29368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return kUseCell; 29371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 29381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 29391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 29401e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockHValue* HGraphBuilder::BuildContextChainWalk(Variable* var) { 29411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(var->IsContextSlot()); 29428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* context = new(zone()) HContext; 29431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 2944e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int length = info()->scope()->ContextChainLength(var->scope()); 29451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block while (length-- > 0) { 29468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch context = new(zone()) HOuterContext(context); 29471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 29481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 29491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return context; 2950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 29548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 29558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 29568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 2957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* variable = expr->AsVariable(); 2958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (variable == NULL) { 29598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("reference to rewritten variable"); 2960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (variable->IsStackAllocated()) { 2961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { 29628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("unsupported context for arguments object"); 2963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(environment()->Lookup(variable)); 2965b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else if (variable->IsContextSlot()) { 2966b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (variable->mode() == Variable::CONST) { 29678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("reference to const context slot"); 2968b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 29691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* context = BuildContextChainWalk(variable); 29701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int index = variable->AsSlot()->index(); 29718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HLoadContextSlot* instr = new(zone()) HLoadContextSlot(context, index); 2972b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 2973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (variable->is_global()) { 2974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 29758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch GlobalPropertyAccess type = LookupGlobalProperty(variable, &lookup, false); 2976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 29778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (type == kUseCell && 29788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch info()->global_object()->IsAccessCheckNeeded()) { 29798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch type = kUseGeneric; 29808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 29818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 29828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (type == kUseCell) { 29838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<GlobalObject> global(info()->global_object()); 29848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 29858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 29868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HLoadGlobalCell* instr = new(zone()) HLoadGlobalCell(cell, check_hole); 29878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 29888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 29898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 29908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(context); 29918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 29928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(global_object); 29938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HLoadGlobalGeneric* instr = 29948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HLoadGlobalGeneric(context, 29958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch global_object, 29968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch variable->name(), 29978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ast_context()->is_for_typeof()); 29988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr->set_position(expr->position()); 29998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(instr->HasSideEffects()); 30008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 3001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 30038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("reference to a variable which requires dynamic lookup"); 3004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitLiteral(Literal* expr) { 30098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 30108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 30118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 30128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HConstant* instr = 30138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HConstant(expr->handle(), Representation::Tagged()); 3014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 3015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 30198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 30208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 30218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 30228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HRegExpLiteral* instr = new(zone()) HRegExpLiteral(expr->pattern(), 30238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->flags(), 30248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->literal_index()); 3025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 3026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 30308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 30318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 30328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 30338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 30341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 30358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HObjectLiteral* literal = 30368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HObjectLiteral(context, 30378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->constant_properties(), 30388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->fast_elements(), 30398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->literal_index(), 30408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->depth(), 30418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->has_function()); 3042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The object is expected in the bailout environment during computation 3043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the property values and is the value of the entire expression. 3044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(literal); 3045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->CalculateEmitStore(); 3047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < expr->properties()->length(); i++) { 3049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ObjectLiteral::Property* property = expr->properties()->at(i); 3050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (property->IsCompileTimeValue()) continue; 3051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* key = property->key(); 3053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* value = property->value(); 3054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (property->kind()) { 3056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::MATERIALIZED_LITERAL: 3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 3058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Fall through. 3059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::COMPUTED: 3060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (key->handle()->IsSymbol()) { 3061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (property->emit_store()) { 30628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(value)); 3063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 3064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = Handle<String>::cast(key->handle()); 30651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HStoreNamedGeneric* store = 30668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HStoreNamedGeneric( 30678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch context, 30688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch literal, 30698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch name, 30708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch value, 30718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch function_strict_mode()); 30721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(store); 3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(key->id()); 3074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 30758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForEffect(value)); 3076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 3078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Fall through. 3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::PROTOTYPE: 3081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::SETTER: 3082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::GETTER: 30838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("Object literal with complex property"); 3084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: UNREACHABLE(); 3085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 308744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 308844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (expr->has_function()) { 308944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return the result of the transformation to fast properties 309044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // instead of the original since this operation changes the map 309144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // of the object. This makes sure that the original object won't 309244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // be used by other optimized code before it is transformed 309344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // (e.g. because of code motion). 30948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HToFastProperties* result = new(zone()) HToFastProperties(Pop()); 309544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(result); 309644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ast_context()->ReturnValue(result); 309744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 309844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ast_context()->ReturnValue(Pop()); 309944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 31048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 31058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 31068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<Expression*>* subexprs = expr->values(); 3108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = subexprs->length(); 3109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HArrayLiteral* literal = new(zone()) HArrayLiteral(expr->constant_elements(), 31118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch length, 31128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->literal_index(), 31138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->depth()); 3114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The array is expected in the bailout environment during computation 3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the property values and is the value of the entire expression. 3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(literal); 3117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HLoadElements* elements = NULL; 3119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; i++) { 3121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* subexpr = subexprs->at(i); 3122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the subexpression is a literal or a simple materialized literal it 3123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // is already set in the cloned array. 3124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 3125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(subexpr)); 3127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 31288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (!Smi::IsValid(i)) return Bailout("Non-smi key in array literal"); 3129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the elements array before the first store. 3131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (elements == NULL) { 31328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch elements = new(zone()) HLoadElements(literal); 3133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(elements); 3134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 31368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValue* key = AddInstruction( 31378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HConstant(Handle<Object>(Smi::FromInt(i)), 31388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Representation::Integer32())); 31398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HStoreKeyedFastElement(elements, key, value)); 3140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(expr->GetIdForElement(i)); 3141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { 31478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 31488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 31498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 31508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("CatchExtensionObject"); 3151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Sets the lookup result and returns true if the store can be inlined. 3155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool ComputeStoredField(Handle<Map> type, 3156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup) { 3158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch type->LookupInDescriptors(NULL, *name, lookup); 3159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!lookup->IsPropertyOrTransition()) return false; 3160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup->type() == FIELD) return true; 3161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return (lookup->type() == MAP_TRANSITION) && 3162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (type->unused_property_fields() > 0); 3163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int ComputeStoredFieldIndex(Handle<Map> type, 3167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup) { 3169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(lookup->type() == FIELD || lookup->type() == MAP_TRANSITION); 3170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup->type() == FIELD) { 3171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return lookup->GetLocalFieldIndexFromMap(*type); 3172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Map* transition = lookup->GetTransitionMapFromMap(*type); 3174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return transition->PropertyIndexFor(*name) - type->inobject_properties(); 3175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, 3180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 3182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> type, 3183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup, 3184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool smi_and_map_check) { 3185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (smi_and_map_check) { 31868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); 31878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckMap(object, type)); 3188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = ComputeStoredFieldIndex(type, name, lookup); 3191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_in_object = index < 0; 3192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = index * kPointerSize; 3193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (index < 0) { 3194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Negative property indices are in-object properties, indexed 3195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // from the end of the fixed part of the object. 3196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch offset += type->instance_size(); 3197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch offset += FixedArray::kHeaderSize; 3199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HStoreNamedField* instr = 32018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HStoreNamedField(object, name, value, is_in_object, offset); 3202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup->type() == MAP_TRANSITION) { 3203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); 3204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_transition(transition); 3205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(fschneider): Record the new map type of the object in the IR to 3206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // enable elimination of redundant checks after the transition store. 3207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->SetFlag(HValue::kChangesMaps); 3208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 3210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, 3214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value) { 32168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 32171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 32188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HStoreNamedGeneric( 32198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch context, 32208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch object, 32218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch name, 32228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch value, 32238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch function_strict_mode()); 3224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, 3228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 3229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* expr) { 3230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = (expr->AsProperty() != NULL) 3231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? expr->AsProperty() 3232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : expr->AsAssignment()->target()->AsProperty(); 3233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* key = prop->key()->AsLiteral(); 3234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = Handle<String>::cast(key->handle()); 3235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!name.is_null()); 3236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 3238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types = expr->GetReceiverTypes(); 3239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_monomorphic = expr->IsMonomorphic() && 3240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ComputeStoredField(types->first(), name, &lookup); 3241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return is_monomorphic 3243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? BuildStoreNamedField(object, name, value, types->first(), &lookup, 3244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true) // Needs smi and map check. 3245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : BuildStoreNamedGeneric(object, name, value); 3246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, 3250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* object, 3251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 3252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types, 3253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name) { 3254e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(ager): We should recognize when the prototype chains for different 3255e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // maps are identical. In that case we can avoid repeatedly generating the 3256e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // same prototype map checks. 3257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int count = 0; 3258e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* join = NULL; 3259e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch for (int i = 0; i < types->length() && count < kMaxStorePolymorphism; ++i) { 3260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = types->at(i); 3261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 3262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (ComputeStoredField(map, name, &lookup)) { 3263e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (count == 0) { 32648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); // Only needed once. 3265e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch join = graph()->CreateBasicBlock(); 3266e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ++count; 3268e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_true = graph()->CreateBasicBlock(); 3269e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_false = graph()->CreateBasicBlock(); 32708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCompareMap* compare = 32718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCompareMap(object, map, if_true, if_false); 3272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Finish(compare); 3273e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3274e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(if_true); 3275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = 3276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildStoreNamedField(object, name, value, map, &lookup, false); 3277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3278e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Goto will add the HSimulate for the store. 3279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 3280e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!ast_context()->IsEffect()) Push(value); 3281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(join); 3282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3283e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(if_false); 3284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3287e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Finish up. Unconditionally deoptimize if we've handled all the maps we 3288e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // know about and do not want to handle ones we've never seen. Otherwise 3289e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // use a generic IC. 3290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 329144f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->FinishExitWithDeoptimization(); 3292e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 32931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HInstruction* instr = BuildStoreNamedGeneric(object, name, value); 3294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 3296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3297e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (join != NULL) { 3298e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!ast_context()->IsEffect()) Push(value); 3299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Goto(join); 3300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3301e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // The HSimulate for the store should not see the stored value in 3302e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // effect contexts (it is not materialized at expr->id() in the 3303e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // unoptimized code). 3304e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->HasSideEffects()) { 3305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (ast_context()->IsEffect()) { 3306e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddSimulate(expr->id()); 3307e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 3308e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Push(value); 3309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddSimulate(expr->id()); 3310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 3311e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3312e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 3313e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnValue(value); 3314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return; 33159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 3316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3317e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(join != NULL); 3319e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch join->SetJoinId(expr->id()); 3320e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(join); 3321e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 3322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 3326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = expr->target()->AsProperty(); 3327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(prop != NULL); 3328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->RecordTypeFeedback(oracle()); 33298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 3330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = NULL; 3332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 3333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->key()->IsPropertyName()) { 3335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named store. 33368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 3337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = Pop(); 3338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* object = Pop(); 3339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* key = prop->key()->AsLiteral(); 3341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = Handle<String>::cast(key->handle()); 3342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!name.is_null()); 3343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types = expr->GetReceiverTypes(); 3345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 3346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->IsMonomorphic()) { 3348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = BuildStoreNamed(object, value, expr); 3349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (types != NULL && types->length() > 1) { 3351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandlePolymorphicStoreNamedField(expr, object, value, types, name); 3352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 3353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block instr = BuildStoreNamedGeneric(object, name, value); 3356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed store. 33608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 33618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 3362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = Pop(); 3363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 3364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* object = Pop(); 33658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = BuildStoreKeyed(object, key, value, expr); 3366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(value); 3368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 3370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Because not every expression has a position and there is not common 3376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// superclass of Assignment and CountOperation, we cannot just pass the 3377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// owning expression instead of position and ast_id separately. 3378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, 3379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 3380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int position, 3381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 3382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 33838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, true); 33848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (type == kUseCell) { 33858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 33868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<GlobalObject> global(info()->global_object()); 33878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 33888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* instr = new(zone()) HStoreGlobalCell(value, cell, check_hole); 33898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr->set_position(position); 33908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(instr); 33918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (instr->HasSideEffects()) AddSimulate(ast_id); 33928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 33938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 33948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(context); 33958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 33968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(global_object); 33978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStoreGlobalGeneric* instr = 33988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HStoreGlobalGeneric(context, 33998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch global_object, 34008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch var->name(), 34018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch value, 34028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch function_strict_mode()); 34038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr->set_position(position); 34048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(instr); 34058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(instr->HasSideEffects()); 34068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (instr->HasSideEffects()) AddSimulate(ast_id); 34078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 3408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 3412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* target = expr->target(); 3413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = target->AsVariableProxy(); 3414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = proxy->AsVariable(); 3415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = target->AsProperty(); 3416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(var == NULL || prop == NULL); 3417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We have a second position recorded in the FullCodeGenerator to have 3419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // type feedback for the binary operation. 3420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BinaryOperation* operation = expr->binary_operation(); 3421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var != NULL) { 34238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(operation)); 3424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var->is_global()) { 3426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleGlobalVariableAssignment(var, 3427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Top(), 3428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->position(), 3429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->AssignmentId()); 3430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (var->IsStackAllocated()) { 3431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Bind(var, Top()); 3432e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (var->IsContextSlot()) { 3433e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HValue* context = BuildContextChainWalk(var); 3434e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int index = var->AsSlot()->index(); 34358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStoreContextSlot* instr = 34368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HStoreContextSlot(context, index, Top()); 3437e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddInstruction(instr); 3438e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3439e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 34408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("compound assignment to lookup slot"); 3441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (prop != NULL) { 3445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prop->RecordTypeFeedback(oracle()); 3446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->key()->IsPropertyName()) { 3448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named property. 34498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 3450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Top(); 3451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* load = NULL; 3453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->IsMonomorphic()) { 3454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 3455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = prop->GetReceiverTypes()->first(); 3456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamed(obj, prop, map, name); 3457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamedGeneric(obj, prop); 3459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 3461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); 3462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 34638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 3464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 3465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 3466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = BuildBinaryOperation(operation, left, right); 3468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(instr); 3469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) AddSimulate(operation->id()); 3470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* store = BuildStoreNamed(obj, instr, prop); 3472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 3473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop the simulated receiver and value. Return the value. 3474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(2); 3475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(instr); 3476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed property. 34818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 34828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 3483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = environment()->ExpressionStackAt(1); 3484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = environment()->ExpressionStackAt(0); 3485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 34868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* load = BuildLoadKeyed(obj, key, prop); 3487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 3488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); 3489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 34908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 3491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 3492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 3493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = BuildBinaryOperation(operation, left, right); 3495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(instr); 3496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) AddSimulate(operation->id()); 3497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 34988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->RecordTypeFeedback(oracle()); 34998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* store = BuildStoreKeyed(obj, key, instr, expr); 3500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 3501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop the simulated receiver, key, and value. Return the value. 3502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(3); 3503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(instr); 3504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 35098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("invalid lhs in compound assignment"); 3510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitAssignment(Assignment* expr) { 35158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 35168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 35178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = expr->target()->AsVariableProxy(); 3519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = proxy->AsVariable(); 3520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = expr->target()->AsProperty(); 3521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(var == NULL || prop == NULL); 3522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->is_compound()) { 3524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleCompoundAssignment(expr); 3525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 3526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var != NULL) { 35298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (proxy->IsArguments()) return Bailout("assignment to arguments"); 3530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Handle the assignment. 35321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (var->IsStackAllocated()) { 35331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* value = NULL; 35341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Handle stack-allocated variables on the right-hand side directly. 35351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We do not allow the arguments object to occur in a context where it 35361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // may escape, but assignments to stack-allocated locals are 35371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // permitted. Handling such assignments here bypasses the check for 35381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the arguments object in VisitVariableProxy. 35391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Variable* rhs_var = expr->value()->AsVariableProxy()->AsVariable(); 35401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (rhs_var != NULL && rhs_var->IsStackAllocated()) { 35411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = environment()->Lookup(rhs_var); 35421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 35438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 35441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block value = Pop(); 35451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 35461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Bind(var, value); 35471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ast_context()->ReturnValue(value); 35481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (var->IsContextSlot() && var->mode() != Variable::CONST) { 35508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 35511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* context = BuildContextChainWalk(var); 35521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int index = var->AsSlot()->index(); 35538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStoreContextSlot* instr = 35548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HStoreContextSlot(context, index, Top()); 35551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(instr); 35561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 35571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ast_context()->ReturnValue(Pop()); 35581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 35591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (var->is_global()) { 35608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->value())); 3561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleGlobalVariableAssignment(var, 3562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Top(), 3563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->position(), 3564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->AssignmentId()); 35651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ast_context()->ReturnValue(Pop()); 35661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3567b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } else { 35688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("assignment to LOOKUP or const CONTEXT variable"); 3569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (prop != NULL) { 3572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandlePropertyAssignment(expr); 3573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 35748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("invalid left-hand side in assignment"); 3575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThrow(Throw* expr) { 35808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 35818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 35828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't optimize functions with invalid left-hand sides in 3584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // assignments, count operations, or for-in. Consequently throw can 3585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // currently only occur in an effect context. 3586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ast_context()->IsEffect()); 35878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->exception())); 3588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = environment()->Pop(); 35908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HThrow* instr = new(zone()) HThrow(value); 3591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 35921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(instr); 35931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddSimulate(expr->id()); 35948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch current_block()->FinishExit(new(zone()) HAbnormalExit); 3595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 3596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 3600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr, 3601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> type, 3602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup, 3603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool smi_and_map_check) { 3604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (smi_and_map_check) { 36058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); 36068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckMap(object, type)); 3607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = lookup->GetLocalFieldIndexFromMap(*type); 3610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (index < 0) { 3611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Negative property indices are in-object properties, indexed 3612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // from the end of the fixed part of the object. 3613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = (index * kPointerSize) + type->instance_size(); 36148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HLoadNamedField(object, true, offset); 3615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Non-negative property indices are in the properties array. 3617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = (index * kPointerSize) + FixedArray::kHeaderSize; 36188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HLoadNamedField(object, false, offset); 3619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, 3624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr) { 3625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(expr->key()->IsPropertyName()); 3626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Object> name = expr->key()->AsLiteral()->handle(); 36278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 36281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 36298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HLoadNamedGeneric(context, obj, name); 3630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, 3634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr, 3635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map, 3636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name) { 3637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 3638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->LookupInDescriptors(NULL, *name, &lookup); 3639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup.IsProperty() && lookup.type() == FIELD) { 3640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return BuildLoadNamedField(obj, 3641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr, 3642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map, 3643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &lookup, 3644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true); 3645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { 36468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(obj)); 36478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckMap(obj, map)); 3648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); 36498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HConstant(function, Representation::Tagged()); 3650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return BuildLoadNamedGeneric(obj, expr); 3652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 3657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key) { 36588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 36591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 36608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HLoadKeyedGeneric(context, object, key); 3661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, 3665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key, 3666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr) { 3667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 36688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); 3669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = expr->GetMonomorphicReceiverType(); 3670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(map->has_fast_elements()); 36718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckMap(object, map)); 36729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block bool is_array = (map->instance_type() == JS_ARRAY_TYPE); 36738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HLoadElements* elements = new(zone()) HLoadElements(object); 36749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block HInstruction* length = NULL; 36759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (is_array) { 36768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch length = AddInstruction(new(zone()) HJSArrayLength(object)); 36778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HBoundsCheck(key, length)); 36789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block AddInstruction(elements); 36799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 36809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block AddInstruction(elements); 36818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch length = AddInstruction(new(zone()) HFixedArrayLength(elements)); 36828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HBoundsCheck(key, length)); 36839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 36848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HLoadKeyedFastElement(elements, key); 3685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 368844f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHInstruction* HGraphBuilder::BuildLoadKeyedSpecializedArrayElement( 368944f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* object, 369044f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* key, 369144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Property* expr) { 36921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 36938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); 36941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Map> map = expr->GetMonomorphicReceiverType(); 36951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!map->has_fast_elements()); 369644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(map->has_external_array_elements()); 36978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckMap(object, map)); 36988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HLoadElements* elements = new(zone()) HLoadElements(object); 36991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(elements); 37008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* length = new(zone()) HExternalArrayLength(elements); 3701e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddInstruction(length); 37028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HBoundsCheck(key, length)); 370344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HLoadExternalArrayPointer* external_elements = 37048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HLoadExternalArrayPointer(elements); 37051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(external_elements); 370644f0eee88ff00398ff7f715fab053374d808c90dSteve Block HLoadKeyedSpecializedArrayElement* pixel_array_value = 37078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HLoadKeyedSpecializedArrayElement( 37088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch external_elements, key, expr->external_array_type()); 37091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return pixel_array_value; 37101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 37111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 37138b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyed(HValue* obj, 37148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValue* key, 37158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Property* prop) { 37168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (prop->IsMonomorphic()) { 37178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Map> receiver_type(prop->GetMonomorphicReceiverType()); 37188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // An object has either fast elements or pixel array elements, but never 37198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // both. Pixel array maps that are assigned to pixel array elements are 37208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // always created with the fast elements flag cleared. 37218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (receiver_type->has_external_array_elements()) { 37228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return BuildLoadKeyedSpecializedArrayElement(obj, key, prop); 37238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else if (receiver_type->has_fast_elements()) { 37248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return BuildLoadKeyedFastElement(obj, key, prop); 37258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 37268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 37278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return BuildLoadKeyedGeneric(obj, key); 37288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 37298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 37308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 3731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 3732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key, 3733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value) { 37348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 37351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 37368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HStoreKeyedGeneric( 37378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch context, 37388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch object, 37398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch key, 37408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch value, 37418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch function_strict_mode()); 3742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object, 3746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key, 3747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* val, 3748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* expr) { 3749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(expr->IsMonomorphic()); 37508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); 3751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = expr->GetMonomorphicReceiverType(); 3752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(map->has_fast_elements()); 37538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckMap(object, map)); 37548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HLoadElements(object)); 37558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckMap( 37568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch elements, isolate()->factory()->fixed_array_map())); 3757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_array = (map->instance_type() == JS_ARRAY_TYPE); 3758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* length = NULL; 3759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_array) { 37608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch length = AddInstruction(new(zone()) HJSArrayLength(object)); 3761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 37628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch length = AddInstruction(new(zone()) HFixedArrayLength(elements)); 3763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 37648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HBoundsCheck(key, length)); 37658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HStoreKeyedFastElement(elements, key, val); 3766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 376944f0eee88ff00398ff7f715fab053374d808c90dSteve BlockHInstruction* HGraphBuilder::BuildStoreKeyedSpecializedArrayElement( 3770e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HValue* object, 3771e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HValue* key, 3772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HValue* val, 37738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Expression* expr) { 3774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(expr->IsMonomorphic()); 37758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(object)); 3776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<Map> map = expr->GetMonomorphicReceiverType(); 3777e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(!map->has_fast_elements()); 377844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(map->has_external_array_elements()); 37798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckMap(object, map)); 37808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HLoadElements* elements = new(zone()) HLoadElements(object); 3781e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddInstruction(elements); 37828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* length = AddInstruction( 37838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HExternalArrayLength(elements)); 37848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HBoundsCheck(key, length)); 378544f0eee88ff00398ff7f715fab053374d808c90dSteve Block HLoadExternalArrayPointer* external_elements = 37868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HLoadExternalArrayPointer(elements); 3787e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddInstruction(external_elements); 37888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HStoreKeyedSpecializedArrayElement( 378944f0eee88ff00398ff7f715fab053374d808c90dSteve Block external_elements, 379044f0eee88ff00398ff7f715fab053374d808c90dSteve Block key, 379144f0eee88ff00398ff7f715fab053374d808c90dSteve Block val, 37928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->external_array_type()); 37938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch} 37948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 37958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 37968b112d2025046f85ef7f6be087c6129c872ebad2Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyed(HValue* object, 37978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValue* key, 37988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValue* value, 37998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Expression* expr) { 38008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (expr->IsMonomorphic()) { 38018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Handle<Map> receiver_type(expr->GetMonomorphicReceiverType()); 38028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // An object has either fast elements or external array elements, but 38038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // never both. Pixel array maps that are assigned to pixel array elements 38048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // are always created with the fast elements flag cleared. 38058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (receiver_type->has_external_array_elements()) { 38068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return BuildStoreKeyedSpecializedArrayElement(object, 38078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch key, 38088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch value, 38098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr); 38108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else if (receiver_type->has_fast_elements()) { 38118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return BuildStoreKeyedFastElement(object, key, value, expr); 38128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 38138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 38148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return BuildStoreKeyedGeneric(object, key, value); 3815e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 3816e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3817e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 3818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryArgumentsAccess(Property* expr) { 3819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = expr->obj()->AsVariableProxy(); 3820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (proxy == NULL) return false; 3821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!proxy->var()->IsStackAllocated()) return false; 3822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 3823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 3824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* result = NULL; 3827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->key()->IsPropertyName()) { 3828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 3829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!name->IsEqualTo(CStrVector("length"))) return false; 38308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 38318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch result = new(zone()) HArgumentsLength(elements); 3832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3833e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Push(graph()->GetArgumentsObject()); 3834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(expr->key()); 38358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return true; 3836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 3837e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); // Arguments object. 38388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 38398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* length = AddInstruction( 38408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HArgumentsLength(elements)); 38418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HBoundsCheck(key, length)); 38428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch result = new(zone()) HAccessArgumentsAt(elements, length, key); 3843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 3845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 3846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitProperty(Property* expr) { 38508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 38518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 38528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 3853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->RecordTypeFeedback(oracle()); 3854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (TryArgumentsAccess(expr)) return; 3856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 38578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->obj())); 3858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 3860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->IsArrayLength()) { 3861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* array = Pop(); 38628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(array)); 38638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckInstanceType(array, 38648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch JS_ARRAY_TYPE, 38658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch JS_ARRAY_TYPE)); 38668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HJSArrayLength(array); 38679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 38681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else if (expr->IsStringLength()) { 38691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* string = Pop(); 38708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(string)); 38718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckInstanceType(string, 38728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch FIRST_STRING_TYPE, 38738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LAST_STRING_TYPE)); 38748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HStringLength(string); 387544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (expr->IsStringAccess()) { 38768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->key())); 387744f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* index = Pop(); 387844f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* string = Pop(); 387944f0eee88ff00398ff7f715fab053374d808c90dSteve Block HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); 388044f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(char_code); 38818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HStringCharFromCode(char_code); 38821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 38839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else if (expr->IsFunctionPrototype()) { 38849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block HValue* function = Pop(); 38858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(function)); 38868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HLoadFunctionPrototype(function); 3887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (expr->key()->IsPropertyName()) { 3889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 3890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types = expr->GetReceiverTypes(); 3891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Pop(); 3893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->IsMonomorphic()) { 3894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = BuildLoadNamed(obj, expr, types->first(), name); 3895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (types != NULL && types->length() > 1) { 38968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(obj)); 38978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HLoadNamedFieldPolymorphic(obj, types, name); 3898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = BuildLoadNamedGeneric(obj, expr); 3900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 39038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->key())); 3904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 3906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Pop(); 39078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = BuildLoadKeyed(obj, key, expr); 3908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddCheckConstantFunction(Call* expr, 3915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver, 3916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> receiver_map, 3917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool smi_and_map_check) { 3918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Constant functions have the nice property that the map will change if they 3919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // are overwritten. Therefore it is enough to check the map of the holder and 3920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // its prototypes. 3921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (smi_and_map_check) { 39228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(receiver)); 39238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckMap(receiver, receiver_map)); 3924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!expr->holder().is_null()) { 39268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckPrototypeMaps( 3927b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<JSObject>(JSObject::cast(receiver_map->prototype())), 3928b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch expr->holder())); 3929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, 3934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver, 3935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types, 3936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name) { 3937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(ager): We should recognize when the prototype chains for different 3938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // maps are identical. In that case we can avoid repeatedly generating the 3939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // same prototype map checks. 394044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int argument_count = expr->arguments()->length() + 1; // Includes receiver. 394144f0eee88ff00398ff7f715fab053374d808c90dSteve Block int count = 0; 394244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* join = NULL; 394344f0eee88ff00398ff7f715fab053374d808c90dSteve Block for (int i = 0; i < types->length() && count < kMaxCallPolymorphism; ++i) { 3944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = types->at(i); 3945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->ComputeTarget(map, name)) { 394644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (count == 0) { 39478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Only needed once. 39488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(receiver)); 394944f0eee88ff00398ff7f715fab053374d808c90dSteve Block join = graph()->CreateBasicBlock(); 395044f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 395144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ++count; 395244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* if_true = graph()->CreateBasicBlock(); 395344f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* if_false = graph()->CreateBasicBlock(); 39548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCompareMap* compare = 39558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCompareMap(receiver, map, if_true, if_false); 395644f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->Finish(compare); 395744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 395844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(if_true); 3959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddCheckConstantFunction(expr, receiver, map, false); 3960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 3961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Trying to inline the polymorphic call to %s\n", 3962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *name->ToCString()); 3963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 39648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (FLAG_polymorphic_inlining && TryInline(expr)) { 39658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Trying to inline will signal that we should bailout from the 39668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // entire compilation by setting stack overflow on the visitor. 39678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (HasStackOverflow()) return; 39688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 3969e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HCallConstantFunction* call = 39708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallConstantFunction(expr->target(), argument_count); 3971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 39721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PreProcessCall(call); 397344f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(call); 397444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!ast_context()->IsEffect()) Push(call); 3975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 397644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 397744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (current_block() != NULL) current_block()->Goto(join); 397844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(if_false); 3979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 398244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Finish up. Unconditionally deoptimize if we've handled all the maps we 398344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // know about and do not want to handle ones we've never seen. Otherwise 398444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // use a generic IC. 398544f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (count == types->length() && FLAG_deoptimize_uncommon_cases) { 398644f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->FinishExitWithDeoptimization(); 398744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 39888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 39891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 39908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallNamed* call = new(zone()) HCallNamed(context, name, argument_count); 3991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 39921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PreProcessCall(call); 3993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 399444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (join != NULL) { 399544f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(call); 399644f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!ast_context()->IsEffect()) Push(call); 399744f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->Goto(join); 399844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 399944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ast_context()->ReturnInstruction(call, expr->id()); 400044f0eee88ff00398ff7f715fab053374d808c90dSteve Block return; 40019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 4002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 400344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 400444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // We assume that control flow is always live after an expression. So 400544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // even without predecessors to the join block, we set it as the exit 400644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // block and continue by adding instructions there. 400744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(join != NULL); 400844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (join->HasPredecessor()) { 40098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(join); 401044f0eee88ff00398ff7f715fab053374d808c90dSteve Block join->SetJoinId(expr->id()); 401144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); 40128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 40138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(NULL); 401444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 4015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4018e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::TraceInline(Handle<JSFunction> target, const char* reason) { 4019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (FLAG_trace_inlining) { 4020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (reason == NULL) { 40218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // We are currently in the context of inlined function thus we have 40228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // to go to an outer FunctionState to get caller. 40238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); 40248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SmartPointer<char> caller = 40258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch function_state()->outer()->compilation_info()->function()-> 40268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch debug_name()->ToCString(); 4027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF("Inlined %s called from %s.\n", *callee, *caller); 4028e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 40298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); 40308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch SmartPointer<char> caller = 40318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch info()->function()->debug_name()->ToCString(); 4032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch PrintF("Did not inline %s called from %s (%s).\n", 4033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch *callee, *caller, reason); 4034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryInline(Call* expr) { 4040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!FLAG_use_inlining) return false; 4041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Precondition: call is monomorphic and we have found a target with the 4043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // appropriate arity. 4044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> target = expr->target(); 4045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do a quick check on source code length to avoid parsing large 4047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // inlining candidates. 4048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { 4049e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "target text too big"); 4050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Target must be inlineable. 4054e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!target->IsInlineable()) { 4055e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "target not inlineable"); 4056e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 4057e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // No context change required. 4060e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CompilationInfo* outer_info = info(); 4061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (target->context() != outer_info->closure()->context() || 4062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_info->scope()->contains_with() || 4063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_info->scope()->num_heap_slots() > 0) { 4064e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "target requires context change"); 4065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 40688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // Don't inline deeper than kMaxInliningLevels calls. 4069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* env = environment(); 40708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int current_level = 1; 40718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch while (env->outer() != NULL) { 40728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (current_level == Compiler::kMaxInliningLevels) { 40738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch TraceInline(target, "inline depth limit reached"); 40748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return false; 40758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 40768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch current_level++; 40778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch env = env->outer(); 4078e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Don't inline recursive functions. 4081e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (target->shared() == outer_info->closure()->shared()) { 4082e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "target is recursive"); 4083e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 4084e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't want to add more than a certain number of nodes from inlining. 4087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) { 4088e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "cumulative AST node limit reached"); 4089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int count_before = AstNode::Count(); 4093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Parse and allocate variables. 4095e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CompilationInfo target_info(target); 4096e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!ParserApi::Parse(&target_info) || 4097e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !Scope::Analyze(&target_info)) { 409844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (target_info.isolate()->has_pending_exception()) { 4099e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Parse or scope error, never optimize this function. 41001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block SetStackOverflow(); 4101e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch target->shared()->set_optimization_disabled(true); 41021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 4103e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "parse failure"); 4104e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 4105e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4106e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4107e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (target_info.scope()->num_heap_slots() > 0) { 4108e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "target has context-allocated variables"); 4109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4111e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FunctionLiteral* function = target_info.function(); 4112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Count the number of AST nodes added by inlining this call. 4114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int nodes_added = AstNode::Count() - count_before; 4115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { 4116e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "target AST is too large"); 4117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check if we can handle all declarations in the inlined functions. 4121e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitDeclarations(target_info.scope()->declarations()); 4122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) { 4123e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "target has non-trivial declaration"); 4124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ClearStackOverflow(); 4125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Don't inline functions that uses the arguments object or that 4129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // have a mismatching number of parameters. 4130e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<SharedFunctionInfo> target_shared(target->shared()); 4131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity = expr->arguments()->length(); 4132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (function->scope()->arguments() != NULL || 4133e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch arity != target_shared->formal_parameter_count()) { 4134e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "target requires special argument handling"); 4135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // All statements in the body must be inlineable. 4139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0, count = function->body()->length(); i < count; ++i) { 4140e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!function->body()->at(i)->IsInlineable()) { 4141e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "target contains unsupported syntax"); 4142e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 4143e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Generate the deoptimization data for the unoptimized version of 4147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the target function if we don't already have it. 4148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!target_shared->has_deoptimization_support()) { 4149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Note that we compile here using the same AST that we will use for 4150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // generating the optimized inline code. 4151e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch target_info.EnableDeoptimizationSupport(); 4152e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (!FullCodeGenerator::MakeCode(&target_info)) { 4153e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "could not generate deoptimization info"); 4154e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch return false; 4155e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4156e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch target_shared->EnableDeoptimizationSupport(*target_info.code()); 4157e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Compiler::RecordFunctionCompilation(Logger::FUNCTION_TAG, 4158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch &target_info, 4159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch target_shared); 4160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4162e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // ---------------------------------------------------------------- 4163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Save the pending call context and type feedback oracle. Set up new ones 4164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // for the inlined function. 4165e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(target_shared->has_deoptimization_support()); 4166e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TypeFeedbackOracle target_oracle( 4167e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<Code>(target_shared->code()), 4168b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Handle<Context>(target->context()->global_context())); 4169e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch FunctionState target_state(this, &target_info, &target_oracle); 4170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 417144f0eee88ff00398ff7f715fab053374d808c90dSteve Block HConstant* undefined = graph()->GetConstantUndefined(); 417244f0eee88ff00398ff7f715fab053374d808c90dSteve Block HEnvironment* inner_env = 417344f0eee88ff00398ff7f715fab053374d808c90dSteve Block environment()->CopyForInlining(target, function, true, undefined); 417444f0eee88ff00398ff7f715fab053374d808c90dSteve Block HBasicBlock* body_entry = CreateBasicBlock(inner_env); 417544f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->Goto(body_entry); 417644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 417744f0eee88ff00398ff7f715fab053374d808c90dSteve Block body_entry->SetJoinId(expr->ReturnId()); 417844f0eee88ff00398ff7f715fab053374d808c90dSteve Block set_current_block(body_entry); 41798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HEnterInlined(target, function)); 418044f0eee88ff00398ff7f715fab053374d808c90dSteve Block VisitStatements(function->body()); 4181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) { 4182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Bail out if the inline function did, as we cannot residualize a call 4183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // instead. 4184e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, "inline graph construction failed"); 41858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return true; 4186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Update inlined nodes count. 4189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inlined_count_ += nodes_added; 4190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4191e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TraceInline(target, NULL); 4192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 419344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (current_block() != NULL) { 4194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Add a return of undefined if control can fall off the body. In a 4195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // test context, undefined is false. 4196e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (inlined_test_context() == NULL) { 4197e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(function_return() != NULL); 419844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(call_context()->IsEffect() || call_context()->IsValue()); 419944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (call_context()->IsEffect()) { 420044f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->Goto(function_return(), false); 420144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 420244f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->AddLeaveInlined(undefined, function_return()); 420344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 4204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The graph builder assumes control can reach both branches of a 4206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // test, so we materialize the undefined value and test it rather than 4207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // simply jumping to the false target. 4208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // 4209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(3168478): refactor to avoid this. 4210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty_true = graph()->CreateBasicBlock(); 4211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty_false = graph()->CreateBasicBlock(); 42128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HTest* test = new(zone()) HTest(undefined, empty_true, empty_false); 421344f0eee88ff00398ff7f715fab053374d808c90dSteve Block current_block()->Finish(test); 421444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 421544f0eee88ff00398ff7f715fab053374d808c90dSteve Block empty_true->Goto(inlined_test_context()->if_true(), false); 421644f0eee88ff00398ff7f715fab053374d808c90dSteve Block empty_false->Goto(inlined_test_context()->if_false(), false); 4217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Fix up the function exits. 4221e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (inlined_test_context() != NULL) { 4222e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_true = inlined_test_context()->if_true(); 4223e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* if_false = inlined_test_context()->if_false(); 4224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if_true->SetJoinId(expr->id()); 4225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if_false->SetJoinId(expr->id()); 4226e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ast_context() == inlined_test_context()); 4227e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Pop the return test context from the expression context stack. 4228e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ClearInlinedTestContext(); 4229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Forward to the real test context. 4231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 423344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if_true->Goto(true_target, false); 423444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if_false->Goto(false_target, false); 4235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(kmillikin): Come up with a better way to handle this. It is too 4237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // subtle. NULL here indicates that the enclosing context has no control 4238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // flow to handle. 4239e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(NULL); 4240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 42418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else if (function_return()->HasPredecessor()) { 4242e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch function_return()->SetJoinId(expr->id()); 4243e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(function_return()); 42448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 42458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(NULL); 4246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 42521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Blockbool HGraphBuilder::TryInlineBuiltinFunction(Call* expr, 42531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* receiver, 42541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Map> receiver_map, 42551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block CheckType check_type) { 42561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(check_type != RECEIVER_MAP_CHECK || !receiver_map.is_null()); 4257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Try to inline calls like Math.* as operations in the calling function. 42581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; 4259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 4260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (id) { 42621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block case kStringCharCodeAt: 426344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case kStringCharAt: 42641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (argument_count == 2 && check_type == STRING_CHECK) { 42651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* index = Pop(); 42661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* string = Pop(); 42671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(!expr->holder().is_null()); 42688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckPrototypeMaps( 42691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block oracle()->GetPrototypeForPrimitiveCheck(STRING_CHECK), 42701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block expr->holder())); 427144f0eee88ff00398ff7f715fab053374d808c90dSteve Block HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); 427244f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (id == kStringCharCodeAt) { 427344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ast_context()->ReturnInstruction(char_code, expr->id()); 427444f0eee88ff00398ff7f715fab053374d808c90dSteve Block return true; 427544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 427644f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(char_code); 42778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStringCharFromCode* result = 42788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HStringCharFromCode(char_code); 42791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ast_context()->ReturnInstruction(result, expr->id()); 42801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block return true; 42811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 42821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 4283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathRound: 4284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathFloor: 4285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathAbs: 4286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathSqrt: 4287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathLog: 4288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathSin: 4289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathCos: 42901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (argument_count == 2 && check_type == RECEIVER_MAP_CHECK) { 42911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddCheckConstantFunction(expr, receiver, receiver_map, true); 4292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* argument = Pop(); 4293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(1); // Receiver. 42948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HUnaryMathOperation* op = new(zone()) HUnaryMathOperation(argument, id); 4295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch op->set_position(expr->position()); 4296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(op, expr->id()); 4297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathPow: 43011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (argument_count == 3 && check_type == RECEIVER_MAP_CHECK) { 43021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddCheckConstantFunction(expr, receiver, receiver_map, true); 4303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 4304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 4305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Pop(); // Pop receiver. 4306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* result = NULL; 4307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Use sqrt() if exponent is 0.5 or -0.5. 4308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 4309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double exponent = HConstant::cast(right)->DoubleValue(); 4310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (exponent == 0.5) { 43118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch result = new(zone()) HUnaryMathOperation(left, kMathPowHalf); 4312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (exponent == -0.5) { 4313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* double_one = 43148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HConstant(Handle<Object>(Smi::FromInt(1)), 43158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Representation::Double()); 4316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(double_one); 4317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HUnaryMathOperation* square_root = 43188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HUnaryMathOperation(left, kMathPowHalf); 4319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(square_root); 4320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // MathPowHalf doesn't have side effects so there's no need for 4321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // an environment simulation here. 4322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!square_root->HasSideEffects()); 43238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch result = new(zone()) HDiv(double_one, square_root); 4324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (exponent == 2.0) { 43258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch result = new(zone()) HMul(left, left); 4326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (right->IsConstant() && 43281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HConstant::cast(right)->HasInteger32Value() && 43291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HConstant::cast(right)->Integer32Value() == 2) { 43308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch result = new(zone()) HMul(left, left); 4331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 43331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (result == NULL) { 43348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch result = new(zone()) HPower(left, right); 43351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 4336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 4337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 4341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Not yet supported for inlining. 4342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryCallApply(Call* expr) { 4349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* callee = expr->expression(); 4350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = callee->AsProperty(); 4351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(prop != NULL); 4352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4353e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (info()->scope()->arguments() == NULL) return false; 4354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!name->IsEqualTo(CStrVector("apply"))) return false; 4357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 4359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (args->length() != 2) return false; 4360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 4362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 4363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* arg_two_value = environment()->Lookup(arg_two->var()); 4364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 4365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4366b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (!expr->IsMonomorphic() || 4367b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch expr->check_type() != RECEIVER_MAP_CHECK) return false; 4368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Found pattern f.apply(receiver, arguments). 4370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(prop->obj()); 43718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return true; 4372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* function = Pop(); 4373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(args->at(0)); 43748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (HasStackOverflow() || current_block() == NULL) return true; 4375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver = Pop(); 43768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 43778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); 4378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddCheckConstantFunction(expr, 4379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function, 4380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->GetReceiverTypes()->first(), 4381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true); 4382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* result = 43838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HApplyArguments(function, receiver, length, elements); 4384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_position(expr->position()); 4385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 4386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCall(Call* expr) { 43918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 43928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 43938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 4394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* callee = expr->expression(); 4395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4396e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HInstruction* call = NULL; 4397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = callee->AsProperty(); 4399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop != NULL) { 4400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!prop->key()->IsPropertyName()) { 4401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed function call. 44028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 4403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 44048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 4405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push receiver and key like the non-optimized code generator expects it. 4406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 4407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver = Pop(); 4408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(key); 4409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(receiver); 4410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 44118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 4412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 44138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 44141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 44158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall( 44168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallKeyed(context, key, argument_count)); 4417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 4418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(1); // Key. 4419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(call, expr->id()); 4420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named function call. 4424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->RecordTypeFeedback(oracle()); 4425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (TryCallApply(expr)) return; 4427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 44288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 44298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 4430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->RecordTypeFeedback(oracle()); 4434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types = expr->GetReceiverTypes(); 4435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 44361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* receiver = 44371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block environment()->ExpressionStackAt(expr->arguments()->length()); 44381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (expr->IsMonomorphic()) { 44391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Handle<Map> receiver_map = 44401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block (types == NULL) ? Handle<Map>::null() : types->first(); 44411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (TryInlineBuiltinFunction(expr, 44421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block receiver, 44431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block receiver_map, 44441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block expr->check_type())) { 4445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 444844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (CallStubCompiler::HasCustomCallGenerator(*expr->target()) || 44491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block expr->check_type() != RECEIVER_MAP_CHECK) { 44501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // When the target has a custom call IC generator, use the IC, 445144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // because it is likely to generate better code. Also use the IC 445244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // when a primitive receiver check is required. 44538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 44541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 44558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall( 44568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallNamed(context, name, argument_count)); 44571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 44581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddCheckConstantFunction(expr, receiver, receiver_map, true); 44591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 44608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (TryInline(expr)) return; 44618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall( 44628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallConstantFunction(expr->target(), 44638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch argument_count)); 44641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 4465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (types != NULL && types->length() > 1) { 4466b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); 4467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandlePolymorphicCallNamed(expr, receiver, types, name); 4468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 44718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 44721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 44738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall( 44748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallNamed(context, name, argument_count)); 4475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool global_call = (var != NULL) && var->is_global() && !var->is_this(); 4480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!global_call) { 4482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ++argument_count; 44838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 4484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (global_call) { 4487e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch bool known_global_function = false; 4488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If there is a global property cell for the name at compile time and 4489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // access check is not enabled we assume that the function will not change 4490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // and generate optimized code for calling the function. 44918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch LookupResult lookup; 44928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch GlobalPropertyAccess type = LookupGlobalProperty(var, &lookup, false); 44938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (type == kUseCell && 4494e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !info()->global_object()->IsAccessCheckNeeded()) { 4495e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<GlobalObject> global(info()->global_object()); 44968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch known_global_function = expr->ComputeGlobalTarget(global, &lookup); 4497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 4498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (known_global_function) { 4499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push the global object instead of the global receiver because 4500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // code generated by the full code generator expects it. 45018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 45028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 45031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 45041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PushAndAdd(global_object); 45058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 4506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 45078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 4508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* function = Pop(); 45098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckFunction(function, expr->target())); 4510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Replace the global object with the global receiver. 45128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalReceiver* global_receiver = 45138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HGlobalReceiver(global_object); 4514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Index of the receiver from the top of the expression stack. 4515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const int receiver_index = argument_count - 1; 4516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(global_receiver); 4517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(environment()->ExpressionStackAt(receiver_index)-> 4518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch IsGlobalObject()); 4519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(receiver_index, global_receiver); 4520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 45218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (TryInline(expr)) return; 45228b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall(new(zone()) HCallKnownGlobal(expr->target(), 45238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch argument_count)); 4524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 45258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 45261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 45278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushAndAdd(new(zone()) HGlobalObject(context)); 45288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 4529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 45308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall(new(zone()) HCallGlobal(context, 4531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch var->name(), 4532e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch argument_count)); 4533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 45368b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 45378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGlobalObject* global_object = new(zone()) HGlobalObject(context); 45381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 45391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(global_object); 45408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch PushAndAdd(new(zone()) HGlobalReceiver(global_object)); 45418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 4542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 45438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch call = PreProcessCall(new(zone()) HCallFunction(context, argument_count)); 4544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 4548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(call, expr->id()); 4549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallNew(CallNew* expr) { 45538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 45548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 45558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 4556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The constructor function is also used as the receiver argument to the 4557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // JS construct call builtin. 45588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 45598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitExpressions(expr->arguments())); 4560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 45618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 45621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 45631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 45641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The constructor is both an operand to the instruction and an argument 45651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to the construct call. 45661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block int arg_count = expr->arguments()->length() + 1; // Plus constructor. 45671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* constructor = environment()->ExpressionStackAt(arg_count - 1); 45688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallNew* call = new(zone()) HCallNew(context, constructor, arg_count); 4569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 45701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block PreProcessCall(call); 4571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(call, expr->id()); 4572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for generating inlined runtime functions. 4576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Lookup table for generators for runtime calls that are generated inline. 4578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Elements of the table are member pointers to functions of HGraphBuilder. 4579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 4580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &HGraphBuilder::Generate##Name, 4581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst HGraphBuilder::InlineFunctionGenerator 4583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder::kInlineFunctionGenerators[] = { 4584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 4585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 4586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 4587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef INLINE_FUNCTION_GENERATOR_ADDRESS 4588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 45918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 45928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 45938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 4594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->is_jsruntime()) { 45958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("call to a JavaScript runtime function"); 4596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 459844f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Runtime::Function* function = expr->function(); 4599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(function != NULL); 4600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (function->intrinsic_type == Runtime::INLINE) { 4601e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(expr->name()->length() > 0); 4602e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(expr->name()->Get(0) == '_'); 4603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Call to an inline function. 4604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int lookup_index = static_cast<int>(function->function_id) - 4605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(Runtime::kFirstInlineFunction); 4606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(lookup_index >= 0); 4607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(static_cast<size_t>(lookup_index) < 4608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ARRAY_SIZE(kInlineFunctionGenerators)); 4609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 4610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Call the inline code generator using the pointer-to-member. 4612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch (this->*generator)(expr); 4613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(function->intrinsic_type == Runtime::RUNTIME); 46158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgumentList(expr->arguments())); 4616e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4617e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<String> name = expr->name(); 4618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int argument_count = expr->arguments()->length(); 46198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallRuntime* call = 46208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallRuntime(name, function, argument_count); 4621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(RelocInfo::kNoPosition); 4622e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(argument_count); 4623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(call, expr->id()); 4624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 46298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 46308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 46318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 4632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Value op = expr->op(); 4633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::VOID) { 46348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForEffect(expr->expression())); 4635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(graph()->GetConstantUndefined()); 4636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::DELETE) { 4637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = expr->expression()->AsProperty(); 4638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop == NULL && var == NULL) { 4640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Result of deleting non-property, non-variable reference is true. 4641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Evaluate the subexpression for side effects. 46428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForEffect(expr->expression())); 4643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(graph()->GetConstantTrue()); 4644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (var != NULL && 4645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !var->is_global() && 4646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch var->AsSlot() != NULL && 4647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch var->AsSlot()->type() != Slot::LOOKUP) { 4648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Result of deleting non-global, non-dynamic variables is false. 4649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The subexpression does not have side effects. 4650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(graph()->GetConstantFalse()); 4651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (prop != NULL) { 46521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (prop->is_synthetic()) { 46531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Result of deleting parameters is false, even when they rewrite 46541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to accesses on the arguments object. 46551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ast_context()->ReturnValue(graph()->GetConstantFalse()); 46561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 46578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 46588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 46591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* key = Pop(); 46601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* obj = Pop(); 46618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key); 46621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ast_context()->ReturnInstruction(instr, expr->id()); 46631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 4664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (var->is_global()) { 46658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("delete with global variable"); 4666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 46678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("delete with non-global variable"); 4668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::NOT) { 4670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (ast_context()->IsTest()) { 4671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestContext* context = TestContext::cast(ast_context()); 4672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForControl(expr->expression(), 4673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context->if_false(), 4674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context->if_true()); 4675e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (ast_context()->IsValue()) { 4676e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* materialize_false = graph()->CreateBasicBlock(); 4677e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* materialize_true = graph()->CreateBasicBlock(); 46788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->expression(), 46798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch materialize_false, 46808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch materialize_true)); 46818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 46828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (materialize_false->HasPredecessor()) { 46838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch materialize_false->SetJoinId(expr->expression()->id()); 46848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(materialize_false); 46858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Push(graph()->GetConstantFalse()); 46868b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 46878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch materialize_false = NULL; 46888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 4689e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 46908b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (materialize_true->HasPredecessor()) { 46918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch materialize_true->SetJoinId(expr->expression()->id()); 46928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(materialize_true); 46938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Push(graph()->GetConstantTrue()); 46948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 46958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch materialize_true = NULL; 46968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 4697e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 4698e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* join = 4699e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CreateJoin(materialize_false, materialize_true, expr->id()); 4700e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(join); 47018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (join != NULL) ast_context()->ReturnValue(Pop()); 4702e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 4703e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ast_context()->IsEffect()); 4704e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch VisitForEffect(expr->expression()); 4705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4706e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 470744f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else if (op == Token::TYPEOF) { 47088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForTypeOf(expr->expression())); 470944f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* value = Pop(); 47108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id()); 471144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 471244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 47138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 4714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 4715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 4716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (op) { 4717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_NOT: 47188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HBitNot(value); 4719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SUB: 47218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HMul(value, graph_->GetConstantMinus1()); 472244f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 472344f0eee88ff00398ff7f715fab053374d808c90dSteve Block case Token::ADD: 47248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HMul(value, graph_->GetConstant1()); 4725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 47278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("Value: unsupported unary operation"); 4728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 4731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildIncrement(HValue* value, bool increment) { 4736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* delta = increment 4737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? graph_->GetConstant1() 4738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : graph_->GetConstantMinus1(); 47398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* instr = new(zone()) HAdd(value, delta); 4740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssumeRepresentation(instr, Representation::Integer32()); 4741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 4742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCountOperation(CountOperation* expr) { 47468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 47478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 47488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 47498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Expression* target = expr->expression(); 4750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = target->AsVariableProxy(); 4751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = proxy->AsVariable(); 4752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = target->AsProperty(); 4753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(var == NULL || prop == NULL); 4754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool inc = expr->op() == Token::INC; 4755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var != NULL) { 47578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(target)); 4758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Match the full code generator stack by simulating an extra stack 4760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // element for postfix operations in a non-effect context. 4761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); 4762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* before = has_extra ? Top() : Pop(); 4763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* after = BuildIncrement(before, inc); 4764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(after); 4765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(after); 4766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var->is_global()) { 4768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleGlobalVariableAssignment(var, 4769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch after, 4770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->position(), 4771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->AssignmentId()); 4772e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (var->IsStackAllocated()) { 4773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Bind(var, after); 4774e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (var->IsContextSlot()) { 4775e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HValue* context = BuildContextChainWalk(var); 4776e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch int index = var->AsSlot()->index(); 47778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStoreContextSlot* instr = 47788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HStoreContextSlot(context, index, after); 4779e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch AddInstruction(instr); 4780e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4781e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 47828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("lookup variable in count operation"); 4783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(has_extra ? 2 : 1); 4785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (prop != NULL) { 4788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prop->RecordTypeFeedback(oracle()); 4789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->key()->IsPropertyName()) { 4791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named property. 4792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Match the full code generator stack by simulating an extra stack 4794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // element for postfix operations in a non-effect context. 4795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); 4796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (has_extra) Push(graph_->GetConstantUndefined()); 4797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 47988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 4799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Top(); 4800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* load = NULL; 4802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->IsMonomorphic()) { 4803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = prop->GetReceiverTypes()->first(); 4805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamed(obj, prop, map, name); 4806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamedGeneric(obj, prop); 4808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 48108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (load->HasSideEffects()) AddSimulate(expr->CountId()); 4811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* before = Pop(); 4813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is no deoptimization to after the increment, so we don't need 4814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // to simulate the expression stack after this instruction. 4815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* after = BuildIncrement(before, inc); 4816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(after); 4817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* store = BuildStoreNamed(obj, after, prop); 4819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 4820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Overwrite the receiver in the bailout environment with the result 4822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the operation, and the placeholder with the original value if 4823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // necessary. 4824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(0, after); 4825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (has_extra) environment()->SetExpressionStackAt(1, before); 4826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(has_extra ? 2 : 1); 4828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed property. 4833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Match the full code generator stack by simulate an extra stack element 4835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // for postfix operations in a non-effect context. 4836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); 4837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (has_extra) Push(graph_->GetConstantUndefined()); 4838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 48398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->obj())); 48408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(prop->key())); 4841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = environment()->ExpressionStackAt(1); 4842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = environment()->ExpressionStackAt(0); 4843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 48448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* load = BuildLoadKeyed(obj, key, prop); 4845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 48468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (load->HasSideEffects()) AddSimulate(expr->CountId()); 4847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* before = Pop(); 4849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is no deoptimization to after the increment, so we don't need 4850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // to simulate the expression stack after this instruction. 4851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* after = BuildIncrement(before, inc); 4852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(after); 4853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 48548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch expr->RecordTypeFeedback(oracle()); 48558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* store = BuildStoreKeyed(obj, key, after, expr); 4856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 4857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop the key from the bailout environment. Overwrite the receiver 4859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // with the result of the operation, and the placeholder with the 4860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // original value if necessary. 4861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(1); 4862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(0, after); 4863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (has_extra) environment()->SetExpressionStackAt(1, before); 4864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(has_extra ? 2 : 1); 4866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 48718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("invalid lhs in count operation"); 4872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 48761e0659c275bb392c045087af4f6b0d7565cb3d77Steve BlockHStringCharCodeAt* HGraphBuilder::BuildStringCharCodeAt(HValue* string, 48771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* index) { 48788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(string)); 48798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckInstanceType( 48801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block string, FIRST_STRING_TYPE, LAST_STRING_TYPE)); 48818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStringLength* length = new(zone()) HStringLength(string); 48821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(length); 48838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HBoundsCheck(index, length)); 48848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(zone()) HStringCharCodeAt(string, index); 48851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 48861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 48871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 4888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 4889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left, 4890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right) { 48918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch TypeInfo info = oracle()->BinaryType(expr); 4892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 4893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (expr->op()) { 4894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::ADD: 48958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (info.IsString()) { 48968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(left)); 48978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckInstanceType( 48988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch left, FIRST_STRING_TYPE, LAST_STRING_TYPE)); 48998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(right)); 49008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckInstanceType( 49018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch right, FIRST_STRING_TYPE, LAST_STRING_TYPE)); 49028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HStringAdd(left, right); 49038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 49048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HAdd(left, right); 49058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 4906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SUB: 49088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HSub(left, right); 4909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::MUL: 49118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HMul(left, right); 4912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::MOD: 49148b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HMod(left, right); 4915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::DIV: 49178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HDiv(left, right); 4918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_XOR: 49208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HBitXor(left, right); 4921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_AND: 49238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HBitAnd(left, right); 4924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_OR: 49268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HBitOr(left, right); 4927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SAR: 49298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HSar(left, right); 4930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SHR: 49328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HShr(left, right); 4933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SHL: 49358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HShl(left, right); 4936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 4938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 4939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If we hit an uninitialized binary op stub we will get type info 4941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // for a smi operation. If one of the operands is a constant string 4942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // do not generate code assuming it is a smi operation. 4943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsSmi() && 4944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || 4945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { 4946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 4947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_representation) { 4949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic()); 4950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 49511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Representation rep = ToRepresentation(info); 49521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // We only generate either int32 or generic tagged bitwise operations. 49531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) { 49541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block rep = Representation::Integer32(); 49551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 49561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AssumeRepresentation(instr, rep); 4957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 4958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check for the form (%_ClassOf(foo) === 'BarClass'). 4962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsClassOfTest(CompareOperation* expr) { 4963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->op() != Token::EQ_STRICT) return false; 4964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CallRuntime* call = expr->left()->AsCallRuntime(); 4965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (call == NULL) return false; 4966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* literal = expr->right()->AsLiteral(); 4967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (literal == NULL) return false; 4968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!literal->handle()->IsString()) return false; 4969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 4970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(call->arguments()->length() == 1); 4971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 49768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 49778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 49788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 4979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->op() == Token::COMMA) { 49808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForEffect(expr->left())); 4981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Visit the right subexpression in the same AST context as the entire 4982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // expression. 4983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr->right()); 4984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (expr->op() == Token::AND || expr->op() == Token::OR) { 4986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_logical_and = (expr->op() == Token::AND); 4987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (ast_context()->IsTest()) { 4988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestContext* context = TestContext::cast(ast_context()); 4989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Translate left subexpression. 4990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* eval_right = graph()->CreateBasicBlock(); 4991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_logical_and) { 49928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), 49938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch eval_right, 49948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch context->if_false())); 4995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 49968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), 49978b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch context->if_true(), 49988b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch eval_right)); 4999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Translate right subexpression by visiting it in the same AST 5002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // context as the entire expression. 50038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (eval_right->HasPredecessor()) { 50048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch eval_right->SetJoinId(expr->RightId()); 50058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(eval_right); 50068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Visit(expr->right()); 50078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5009e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (ast_context()->IsValue()) { 50108b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->left())); 5011e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(current_block() != NULL); 5012e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 5013e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We need an extra block to maintain edge-split form. 5014e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* empty_block = graph()->CreateBasicBlock(); 5015e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* eval_right = graph()->CreateBasicBlock(); 5016e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HTest* test = is_logical_and 50178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ? new(zone()) HTest(Top(), eval_right, empty_block) 50188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch : new(zone()) HTest(Top(), empty_block, eval_right); 5019e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch current_block()->Finish(test); 5020e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 5021e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(eval_right); 5022e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); // Value of the left subexpression. 50238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForValue(expr->right())); 5024e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 5025e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* join_block = 5026e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CreateJoin(empty_block, current_block(), expr->id()); 5027e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(join_block); 5028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 5029e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 5030e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 5031e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(ast_context()->IsEffect()); 5032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // In an effect context, we don't need the value of the left 5033e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // subexpression, only its control flow and side effects. We need an 5034e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // extra block to maintain edge-split form. 5035e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* empty_block = graph()->CreateBasicBlock(); 5036e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HBasicBlock* right_block = graph()->CreateBasicBlock(); 5037e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (is_logical_and) { 50388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block)); 5039e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else { 50408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block)); 5041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } 50428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 5043e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TODO(kmillikin): Find a way to fix this. It's ugly that there are 5044e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // actually two empty blocks (one here and one inserted by 5045e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // TestContext::BuildBranch, and that they both have an HSimulate 5046e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // though the second one is not a merge node, and that we really have 5047e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // no good AST ID to put on that first HSimulate. 50488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (empty_block->HasPredecessor()) { 50498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch empty_block->SetJoinId(expr->id()); 50508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 50518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch empty_block = NULL; 50528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 50538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 50548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (right_block->HasPredecessor()) { 50558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch right_block->SetJoinId(expr->RightId()); 50568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch set_current_block(right_block); 50578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_BAILOUT(VisitForEffect(expr->right())); 50588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch right_block = current_block(); 50598b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 50608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch right_block = NULL; 50618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 50628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 50638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HBasicBlock* join_block = 50648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CreateJoin(empty_block, right_block, expr->id()); 5065e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch set_current_block(join_block); 5066e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // We did not materialize any value in the predecessor environments, 5067e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // so there is no need to handle it here. 5068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 50718b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->left())); 50728b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->right())); 5073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 5075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 5076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = BuildBinaryOperation(expr, left, right); 5077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 5078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 5079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) { 5084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value->CheckFlag(HValue::kFlexibleRepresentation)) { 5085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_representation) { 5086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Assume representation for %s to be %s (%d)\n", 5087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->Mnemonic(), 5088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch r.Mnemonic(), 5089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->GetMaximumValueID()); 5090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->ChangeRepresentation(r); 50921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The representation of the value is dictated by type feedback and 50931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // will not be changed later. 5094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->ClearFlag(HValue::kFlexibleRepresentation); 5095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (FLAG_trace_representation) { 5096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("No representation assumed\n"); 5097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HGraphBuilder::ToRepresentation(TypeInfo info) { 5102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsSmi()) return Representation::Integer32(); 5103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsInteger32()) return Representation::Integer32(); 5104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsDouble()) return Representation::Double(); 5105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsNumber()) return Representation::Double(); 5106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::Tagged(); 5107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 51118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 51128b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 51138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 5114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (IsClassOfTest(expr)) { 5115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CallRuntime* call = expr->left()->AsCallRuntime(); 51168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 5118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* literal = expr->right()->AsLiteral(); 5119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> rhs = Handle<String>::cast(literal->handle()); 51208b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* instr = new(zone()) HClassOfTest(value, rhs); 5121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 5122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 5123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 5124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for the pattern: typeof <expression> == <string literal>. 5127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); 5128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* right_literal = expr->right()->AsLiteral(); 5129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && 5130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch left_unary != NULL && left_unary->op() == Token::TYPEOF && 5131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch right_literal != NULL && right_literal->handle()->IsString()) { 51328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForTypeOf(left_unary->expression())); 5133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 51348b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* instr = new(zone()) HTypeofIs(left, 5135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String>::cast(right_literal->handle())); 5136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 5137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 5138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 5139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 51418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->left())); 51428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->right())); 5143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 5145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 5146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Value op = expr->op(); 5147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5148e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch TypeInfo type_info = oracle()->CompareType(expr); 5149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 5150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::INSTANCEOF) { 5151086aeeaae12517475c22695a200be45495516549Ben Murdoch // Check to see if the rhs of the instanceof is a global function not 5152086aeeaae12517475c22695a200be45495516549Ben Murdoch // residing in new space. If it is we assume that the function will stay the 5153086aeeaae12517475c22695a200be45495516549Ben Murdoch // same. 5154086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<JSFunction> target = Handle<JSFunction>::null(); 5155086aeeaae12517475c22695a200be45495516549Ben Murdoch Variable* var = expr->right()->AsVariableProxy()->AsVariable(); 5156086aeeaae12517475c22695a200be45495516549Ben Murdoch bool global_function = (var != NULL) && var->is_global() && !var->is_this(); 5157086aeeaae12517475c22695a200be45495516549Ben Murdoch if (global_function && 5158e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch info()->has_global_object() && 5159e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch !info()->global_object()->IsAccessCheckNeeded()) { 5160086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<String> name = var->name(); 5161e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Handle<GlobalObject> global(info()->global_object()); 5162086aeeaae12517475c22695a200be45495516549Ben Murdoch LookupResult lookup; 5163086aeeaae12517475c22695a200be45495516549Ben Murdoch global->Lookup(*name, &lookup); 5164086aeeaae12517475c22695a200be45495516549Ben Murdoch if (lookup.IsProperty() && 5165086aeeaae12517475c22695a200be45495516549Ben Murdoch lookup.type() == NORMAL && 5166086aeeaae12517475c22695a200be45495516549Ben Murdoch lookup.GetValue()->IsJSFunction()) { 5167086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); 5168086aeeaae12517475c22695a200be45495516549Ben Murdoch // If the function is in new space we assume it's more likely to 5169086aeeaae12517475c22695a200be45495516549Ben Murdoch // change and thus prefer the general IC code. 517044f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (!isolate()->heap()->InNewSpace(*candidate)) { 5171086aeeaae12517475c22695a200be45495516549Ben Murdoch target = candidate; 5172086aeeaae12517475c22695a200be45495516549Ben Murdoch } 5173086aeeaae12517475c22695a200be45495516549Ben Murdoch } 5174086aeeaae12517475c22695a200be45495516549Ben Murdoch } 5175086aeeaae12517475c22695a200be45495516549Ben Murdoch 5176086aeeaae12517475c22695a200be45495516549Ben Murdoch // If the target is not null we have found a known global function that is 5177086aeeaae12517475c22695a200be45495516549Ben Murdoch // assumed to stay the same for this instanceof. 5178086aeeaae12517475c22695a200be45495516549Ben Murdoch if (target.is_null()) { 51798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 51801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 51818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HInstanceOf(context, left, right); 5182086aeeaae12517475c22695a200be45495516549Ben Murdoch } else { 51838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckFunction(right, target)); 51848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HInstanceOfKnownGlobal(left, target); 5185086aeeaae12517475c22695a200be45495516549Ben Murdoch } 5186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::IN) { 51878b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("Unsupported comparison: in"); 5188e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch } else if (type_info.IsNonPrimitive()) { 5189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (op) { 5190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ: 5191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ_STRICT: { 51928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(left)); 5193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); 51948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(new(zone()) HCheckNonSmi(right)); 5195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); 51968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch instr = new(zone()) HCompareJSObjectEq(left, right); 5197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 5198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 52008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("Unsupported non-primitive compare"); 5201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 5202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 52048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCompare* compare = new(zone()) HCompare(left, right, op); 5205e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Representation r = ToRepresentation(type_info); 5206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch compare->SetInputRepresentation(r); 5207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = compare; 5208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 5210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 5211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { 52158b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 52168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 52178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 52188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(expr->expression())); 5219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 52218b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HIsNull* compare = new(zone()) HIsNull(value, expr->is_strict()); 5222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(compare, expr->id()); 5223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThisFunction(ThisFunction* expr) { 52278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(!HasStackOverflow()); 52288b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block() != NULL); 52298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(current_block()->HasPredecessor()); 52308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("ThisFunction"); 5231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDeclaration(Declaration* decl) { 5235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We allow only declarations that do not require code generation. 5236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The following all require code generation: global variables and 5237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // functions, variables with slot type LOOKUP, declarations with 5238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // mode CONST, and functions. 5239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = decl->proxy()->var(); 5240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Slot* slot = var->AsSlot(); 5241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var->is_global() || 5242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (slot != NULL && slot->type() == Slot::LOOKUP) || 5243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch decl->mode() == Variable::CONST || 5244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch decl->fun() != NULL) { 52458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("unsupported declaration"); 5246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Generators for inline runtime functions. 5251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for types. 5252e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSmi(CallRuntime* call) { 5253e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 52548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 52568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HIsSmi* result = new(zone()) HIsSmi(value); 5257e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5261e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsSpecObject(CallRuntime* call) { 5262e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 52638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 5265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HHasInstanceType* result = 52668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); 5267e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5271e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsFunction(CallRuntime* call) { 5272e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 52738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 52758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HHasInstanceType* result = 52768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HHasInstanceType(value, JS_FUNCTION_TYPE); 5277e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5281e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) { 5282e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 52838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 52858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HHasCachedArrayIndex* result = new(zone()) HHasCachedArrayIndex(value); 5286e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5290e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsArray(CallRuntime* call) { 5291e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 52928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 52948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HHasInstanceType* result = new(zone()) HHasInstanceType(value, JS_ARRAY_TYPE); 5295e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5299e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExp(CallRuntime* call) { 5300e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 53018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 53038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HHasInstanceType* result = 53048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HHasInstanceType(value, JS_REGEXP_TYPE); 5305e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5309e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsObject(CallRuntime* call) { 5310e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 53118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 53138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HIsObject* test = new(zone()) HIsObject(value); 5314e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(test, call->id()); 5315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5318e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) { 53198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("inlined runtime function: IsNonNegativeSmi"); 5320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5323e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) { 53248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("inlined runtime function: IsUndetectableObject"); 5325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 5329e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch CallRuntime* call) { 53308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout( 53318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch "inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 5332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 53351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block// Support for construct call checks. 5336e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsConstructCall(CallRuntime* call) { 5337e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 0); 53388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch if (function_state()->outer() != NULL) { 53398b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // We are generating graph for inlined function. Currently 53408b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // constructor inlining is not supported and we can just return 53418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // false from %_IsConstructCall(). 53428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ast_context()->ReturnValue(graph()->GetConstantFalse()); 53438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } else { 53448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ast_context()->ReturnInstruction(new(zone()) HIsConstructCall, call->id()); 53458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 5346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for arguments.length and arguments[?]. 5350e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArgumentsLength(CallRuntime* call) { 5351e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 0); 53528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 53538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HArgumentsLength* result = new(zone()) HArgumentsLength(elements); 5354e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5358e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateArguments(CallRuntime* call) { 5359e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 53608b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* index = Pop(); 53628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* elements = AddInstruction(new(zone()) HArgumentsElements); 53638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInstruction* length = AddInstruction(new(zone()) HArgumentsLength(elements)); 53648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HAccessArgumentsAt* result = 53658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HAccessArgumentsAt(elements, length, index); 5366e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for accessing the class and value fields of an object. 5371e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateClassOf(CallRuntime* call) { 5372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The special form detected by IsClassOfTest is detected before we get here 5373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // and does not cause a bailout. 53748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("inlined runtime function: ClassOf"); 5375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5378e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateValueOf(CallRuntime* call) { 5379e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 53808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 53828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValueOf* result = new(zone()) HValueOf(value); 5383e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5387e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSetValueOf(CallRuntime* call) { 53888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("inlined runtime function: SetValueOf"); 5389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for charCodeAt(n). 5393e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) { 5394e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 2); 53958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 53968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 53971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* index = Pop(); 53981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HValue* string = Pop(); 53991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block HStringCharCodeAt* result = BuildStringCharCodeAt(string, index); 5400e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n]. 5405e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) { 540644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(call->arguments()->length() == 1); 54078b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 540844f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* char_code = Pop(); 54098b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); 541044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ast_context()->ReturnInstruction(result, call->id()); 5411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n]. 5415e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCharAt(CallRuntime* call) { 541644f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(call->arguments()->length() == 2); 54178b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 54188b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 541944f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* index = Pop(); 542044f0eee88ff00398ff7f715fab053374d808c90dSteve Block HValue* string = Pop(); 542144f0eee88ff00398ff7f715fab053374d808c90dSteve Block HStringCharCodeAt* char_code = BuildStringCharCodeAt(string, index); 542244f0eee88ff00398ff7f715fab053374d808c90dSteve Block AddInstruction(char_code); 54238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HStringCharFromCode* result = new(zone()) HStringCharFromCode(char_code); 5424e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for object equality testing. 5429e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateObjectEquals(CallRuntime* call) { 5430e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 2); 54318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 54328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 5433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 5434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 54358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCompareJSObjectEq* result = new(zone()) HCompareJSObjectEq(left, right); 5436e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5440e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateLog(CallRuntime* call) { 5441e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // %_Log is ignored in optimized code. 5442e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnValue(graph()->GetConstantUndefined()); 5443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for Math.random(). 5447e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRandomHeapNumber(CallRuntime* call) { 54488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("inlined runtime function: RandomHeapNumber"); 5449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringAdd. 5453e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringAdd(CallRuntime* call) { 5454e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(2, call->arguments()->length()); 54558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 54568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 54571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 54588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = new(zone()) HCallStub(context, CodeStub::StringAdd, 2); 5459e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(2); 5460e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for SubString. 5465e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSubString(CallRuntime* call) { 5466e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(3, call->arguments()->length()); 54678b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 54688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 54691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 54708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = new(zone()) HCallStub(context, CodeStub::SubString, 3); 5471e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(3); 5472e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringCompare. 5477e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateStringCompare(CallRuntime* call) { 5478e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(2, call->arguments()->length()); 54798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 54808b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 54811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 54828b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 54838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::StringCompare, 2); 5484e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(2); 5485e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for direct calls from JavaScript to native RegExp code. 5490e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpExec(CallRuntime* call) { 5491e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(4, call->arguments()->length()); 54928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 54938b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 54941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 54958b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = new(zone()) HCallStub(context, CodeStub::RegExpExec, 4); 5496e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(4); 5497e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Construct a RegExp exec result with two in-object properties. 5502e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) { 5503e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(3, call->arguments()->length()); 55048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 55058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 55061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 5507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = 55088b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::RegExpConstructResult, 3); 5509e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(3); 5510e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for fast native caches. 5515e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetFromCache(CallRuntime* call) { 55168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("inlined runtime function: GetFromCache"); 5517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for number to string. 5521e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateNumberToString(CallRuntime* call) { 5522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 55238b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 55248b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 55251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 55268b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 55278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::NumberToString, 1); 5528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 5529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast swapping of elements. Takes three expressions, the object and two 5534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// indices. This should only be used if the indices are known to be 5535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// non-negative and within bounds of the elements array at the call site. 5536e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateSwapElements(CallRuntime* call) { 55378b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("inlined runtime function: SwapElements"); 5538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call for custom callbacks. 5542e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateCallFunction(CallRuntime* call) { 55438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch // 1 ~ The function to call is not itself an argument to the call. 55448b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch int arg_count = call->arguments()->length() - 1; 55458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ASSERT(arg_count >= 1); // There's always at least a receiver. 55468b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch 55478b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch for (int i = 0; i < arg_count; ++i) { 55488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgument(call->arguments()->at(i))); 55498b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch } 55508b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->last())); 55518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HValue* function = Pop(); 55528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new HContext; 55538b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch AddInstruction(context); 55548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HInvokeFunction* result = 55558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HInvokeFunction(context, function, arg_count); 55568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Drop(arg_count); 55578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch ast_context()->ReturnInstruction(result, call->id()); 5558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call to math functions. 5562e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathPow(CallRuntime* call) { 5563e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(2, call->arguments()->length()); 55648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 55658b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(1))); 5566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 5567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 55688b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HPower* result = new(zone()) HPower(left, right); 5569e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5573e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSin(CallRuntime* call) { 5574e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 55758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 55768b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 55771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 55788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 55798b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 5580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::SIN); 5581e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 5582e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5586e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathCos(CallRuntime* call) { 5587e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 55888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 55898b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 55901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 55918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 55928b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 5593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::COS); 5594e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 5595e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5599e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathLog(CallRuntime* call) { 5600e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT_EQ(1, call->arguments()->length()); 56018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitArgumentList(call->arguments())); 56028b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HContext* context = new(zone()) HContext; 56031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block AddInstruction(context); 56048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HCallStub* result = 56058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone()) HCallStub(context, CodeStub::TranscendentalCache, 1); 5606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::LOG); 5607e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch Drop(1); 5608e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5612e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateMathSqrt(CallRuntime* call) { 56138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("inlined runtime function: MathSqrt"); 5614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check whether two RegExps are equivalent 5618e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateIsRegExpEquivalent(CallRuntime* call) { 56198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("inlined runtime function: IsRegExpEquivalent"); 5620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5623e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) { 5624e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ASSERT(call->arguments()->length() == 1); 56258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); 5626e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch HValue* value = Pop(); 56278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HGetCachedArrayIndex* result = new(zone()) HGetCachedArrayIndex(value); 5628e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch ast_context()->ReturnInstruction(result, call->id()); 5629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5632e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdochvoid HGraphBuilder::GenerateFastAsciiArrayJoin(CallRuntime* call) { 56338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return Bailout("inlined runtime function: FastAsciiArrayJoin"); 5634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef CHECK_BAILOUT 56388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch#undef CHECK_ALIVE 5639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(HEnvironment* outer, 5642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Scope* scope, 5643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> closure) 5644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : closure_(closure), 5645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_(0), 5646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch assigned_variables_(4), 5647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_(0), 5648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_(0), 5649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_(outer), 5650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pop_count_(0), 5651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch push_count_(0), 5652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_id_(AstNode::kNoNumber) { 5653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); 5654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(const HEnvironment* other) 5658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : values_(0), 5659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch assigned_variables_(0), 5660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_(0), 5661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_(0), 5662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_(NULL), 5663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pop_count_(0), 5664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch push_count_(0), 5665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_id_(other->ast_id()) { 5666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Initialize(other); 5667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::Initialize(int parameter_count, 5671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int local_count, 5672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int stack_height) { 5673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_ = parameter_count; 5674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_ = local_count; 5675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Avoid reallocating the temporaries' backing store on the first Push. 5677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int total = parameter_count + local_count + stack_height; 5678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_.Initialize(total + 4); 5679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < total; ++i) values_.Add(NULL); 5680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 56839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Initialize(const HEnvironment* other) { 56849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block closure_ = other->closure(); 56859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_.AddAll(other->values_); 56869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block assigned_variables_.AddAll(other->assigned_variables_); 56879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block parameter_count_ = other->parameter_count_; 56889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block local_count_ = other->local_count_; 56899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy. 56909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block pop_count_ = other->pop_count_; 56919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block push_count_ = other->push_count_; 56929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ast_id_ = other->ast_id_; 56939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 56949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 56959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 5696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) { 5697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!block->IsLoopHeader()); 5698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(values_.length() == other->values_.length()); 5699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = values_.length(); 5701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; ++i) { 5702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = values_[i]; 5703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != NULL && value->IsPhi() && value->block() == block) { 5704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is already a phi for the i'th value. 5705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = HPhi::cast(value); 5706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Assert index is correct and that we haven't missed an incoming edge. 5707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->merged_index() == i); 5708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->OperandCount() == block->predecessors()->length()); 5709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(other->values_[i]); 5710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (values_[i] != other->values_[i]) { 5711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is a fresh value on the incoming edge, a phi is needed. 5712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(values_[i] != NULL && other->values_[i] != NULL); 57138b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HPhi* phi = new(block->zone()) HPhi(i); 5714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* old_value = values_[i]; 5715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < block->predecessors()->length(); j++) { 5716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(old_value); 5717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(other->values_[i]); 5719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch this->values_[i] = phi; 5720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->AddPhi(phi); 5721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 57269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Bind(int index, HValue* value) { 57279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(value != NULL); 57289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!assigned_variables_.Contains(index)) { 57299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block assigned_variables_.Add(index); 57309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 57319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_[index] = value; 5732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 57359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::HasExpressionAt(int index) const { 57369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return index >= parameter_count_ + local_count_; 57379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 57389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 57399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 57409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::ExpressionStackIsEmpty() const { 57419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int first_expression = parameter_count() + local_count(); 57429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(length() >= first_expression); 57439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return length() == first_expression; 57449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 57459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 57469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 57479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) { 57489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int count = index_from_top + 1; 57499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index = values_.length() - count; 57509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(HasExpressionAt(index)); 57519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // The push count must include at least the element in question or else 57529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // the new value will not be included in this environment's history. 57539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (push_count_ < count) { 57549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // This is the same effect as popping then re-pushing 'count' elements. 57559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block pop_count_ += (count - push_count_); 57569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block push_count_ = count; 57579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 57589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_[index] = value; 57599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 57609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 57619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 57629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Drop(int count) { 57639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = 0; i < count; ++i) { 57649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Pop(); 5765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::Copy() const { 57708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch return new(closure()->GetIsolate()->zone()) HEnvironment(this); 5771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyWithoutHistory() const { 5775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* result = Copy(); 5776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->ClearHistory(); 5777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 5778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const { 5782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* new_env = Copy(); 5783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < values_.length(); ++i) { 57848b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HPhi* phi = new(loop_header->zone()) HPhi(i); 5785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(values_[i]); 5786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_env->values_[i] = phi; 5787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_header->AddPhi(phi); 5788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_env->ClearHistory(); 5790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new_env; 5791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyForInlining(Handle<JSFunction> target, 5795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FunctionLiteral* function, 5796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_speculative, 5797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* undefined) const { 5798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Outer environment is a copy of this one without the arguments. 5799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity = function->scope()->num_parameters(); 5800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* outer = Copy(); 5801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer->Drop(arity + 1); // Including receiver. 5802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer->ClearHistory(); 58038b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch Zone* zone = closure()->GetIsolate()->zone(); 58048b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch HEnvironment* inner = 58058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch new(zone) HEnvironment(outer, function->scope(), target); 5806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the argument values from the original environment. 5807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_speculative) { 5808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i <= arity; ++i) { // Include receiver. 5809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* push = ExpressionStackAt(arity - i); 5810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inner->SetValueAt(i, push); 5811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i <= arity; ++i) { // Include receiver. 5814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inner->SetValueAt(i, ExpressionStackAt(arity - i)); 5815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Initialize the stack-allocated locals to undefined. 5819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int local_base = arity + 1; 5820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int local_count = function->scope()->num_stack_slots(); 5821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < local_count; ++i) { 5822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inner->SetValueAt(local_base + i, undefined); 5823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 58258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch inner->set_ast_id(AstNode::kFunctionEntryId); 5826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return inner; 5827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintTo(StringStream* stream) { 58319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = 0; i < length(); i++) { 5832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (i == 0) stream->Add("parameters\n"); 5833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (i == parameter_count()) stream->Add("locals\n"); 5834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (i == parameter_count() + local_count()) stream->Add("expressions"); 5835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* val = values_.at(i); 5836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("%d: ", i); 5837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (val != NULL) { 5838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch val->PrintNameTo(stream); 5839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("NULL"); 5841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("\n"); 5843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintToStd() { 5848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HeapStringAllocator string_allocator; 5849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StringStream trace(&string_allocator); 5850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintTo(&trace); 5851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("%s", *trace.ToCString()); 5852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceCompilation(FunctionLiteral* function) { 5856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "compilation"); 5857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = function->debug_name(); 5858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", *name->ToCString()); 5859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("method", *name->ToCString()); 5860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); 5861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLithium(const char* name, LChunk* chunk) { 5865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Trace(name, chunk->graph(), chunk); 5866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceHydrogen(const char* name, HGraph* graph) { 5870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Trace(name, graph, NULL); 5871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { 5875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "cfg"); 5876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", name); 5877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HBasicBlock*>* blocks = graph->blocks(); 5878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks->length(); i++) { 5879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* current = blocks->at(i); 5880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag block_tag(this, "block"); 5881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("name", current->block_id()); 5882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty("from_bci", -1); 5883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty("to_bci", -1); 5884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!current->predecessors()->is_empty()) { 5886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIndent(); 5887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("predecessors"); 5888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < current->predecessors()->length(); ++j) { 5889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id()); 5890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("\n"); 5892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("predecessors"); 5894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->end() == NULL || current->end()->FirstSuccessor() == NULL) { 5897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("successors"); 5898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (current->end()->SecondSuccessor() == NULL) { 5899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("successors", 5900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->end()->FirstSuccessor()->block_id()); 5901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("successors", 5903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->end()->FirstSuccessor()->block_id(), 5904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->end()->SecondSuccessor()->block_id()); 5905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("xhandlers"); 5908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("flags"); 5909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->dominator() != NULL) { 5911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("dominator", current->dominator()->block_id()); 5912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk != NULL) { 5915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int first_index = current->first_instruction_index(); 5916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_index = current->last_instruction_index(); 5917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty( 5918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "first_lir_id", 5919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(first_index).Value()); 5920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty( 5921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "last_lir_id", 5922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(last_index).Value()); 5923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 5926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag states_tag(this, "states"); 5927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag locals_tag(this, "locals"); 5928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int total = current->phis()->length(); 5929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("size %d\n", total); 5930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("method \"None\""); 5931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < total; ++j) { 5932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = current->phis()->at(j); 5933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d ", phi->merged_index()); 5934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->PrintNameTo(&trace_); 5935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" "); 5936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->PrintTo(&trace_); 5937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("\n"); 5938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 5942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag HIR_tag(this, "HIR"); 5943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instruction = current->first(); 5944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instruction != NULL) { 5945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int bci = 0; 5946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int uses = instruction->uses()->length(); 5947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d %d ", bci, uses); 5948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction->PrintNameTo(&trace_); 5949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" "); 5950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction->PrintTo(&trace_); 5951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" <|@\n"); 5952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction = instruction->next(); 5953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk != NULL) { 5958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag LIR_tag(this, "LIR"); 5959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int first_index = current->first_instruction_index(); 5960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_index = current->last_instruction_index(); 5961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first_index != -1 && last_index != -1) { 5962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<LInstruction*>* instructions = chunk->instructions(); 5963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = first_index; i <= last_index; ++i) { 5964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LInstruction* linstr = instructions->at(i); 5965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (linstr != NULL) { 5966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d ", 5967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(i).Value()); 5968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch linstr->PrintTo(&trace_); 5969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" <|@\n"); 5970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) { 5979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "intervals"); 5980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", name); 5981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 598244f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges(); 5983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < fixed_d->length(); ++i) { 5984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(fixed_d->at(i), "fixed"); 5985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 598744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges(); 5988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < fixed->length(); ++i) { 5989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(fixed->at(i), "fixed"); 5990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges(); 5993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < live_ranges->length(); ++i) { 5994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(live_ranges->at(i), "object"); 5995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRange(LiveRange* range, const char* type) { 6000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range != NULL && !range->IsEmpty()) { 6001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d %s", range->id(), type); 6002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range->HasRegisterAssigned()) { 6003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op = range->CreateAssignedOperand(); 6004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int assigned_reg = op->index(); 6005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op->IsDoubleRegister()) { 6006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"%s\"", 6007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoubleRegister::AllocationIndexToString(assigned_reg)); 6008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsRegister()); 6010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg)); 6011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (range->IsSpilled()) { 6013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op = range->TopLevel()->GetSpillOperand(); 6014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op->IsDoubleStackSlot()) { 6015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"double_stack:%d\"", op->index()); 6016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsStackSlot()); 6018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"stack:%d\"", op->index()); 6019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int parent_index = -1; 6022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range->IsChild()) { 6023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parent_index = range->parent()->id(); 6024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parent_index = range->id(); 6026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op = range->FirstHint(); 6028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int hint_index = -1; 6029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op != NULL && op->IsUnallocated()) hint_index = op->VirtualRegister(); 6030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" %d %d", parent_index, hint_index); 6031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UseInterval* cur_interval = range->first_interval(); 6032e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch while (cur_interval != NULL && range->Covers(cur_interval->start())) { 6033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" [%d, %d[", 6034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval->start().Value(), 6035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval->end().Value()); 6036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval = cur_interval->next(); 6037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UsePosition* current_pos = range->first_pos(); 6040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current_pos != NULL) { 6041e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) { 6042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" %d M", current_pos->pos().Value()); 6043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_pos = current_pos->next(); 6045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"\"\n"); 6048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::FlushToFile() { 6053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendChars(filename_, *trace_.ToCString(), trace_.length(), false); 6054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Reset(); 6055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 605844f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid HStatistics::Initialize(CompilationInfo* info) { 605944f0eee88ff00398ff7f715fab053374d808c90dSteve Block source_size_ += info->shared_info()->SourceSize(); 606044f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 606144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 606244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStatistics::Print() { 6064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Timing results:\n"); 6065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int64_t sum = 0; 6066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < timing_.length(); ++i) { 6067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch sum += timing_[i]; 6068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < names_.length(); ++i) { 6071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("%30s", names_[i]); 6072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double ms = static_cast<double>(timing_[i]) / 1000; 6073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double percent = static_cast<double>(timing_[i]) * 100 / sum; 6074b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF(" - %7.3f ms / %4.1f %% ", ms, percent); 6075b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch 6076b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch unsigned size = sizes_[i]; 6077b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch double size_percent = static_cast<double>(size) * 100 / total_size_; 6078b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF(" %8u bytes / %4.1f %%\n", size, size_percent); 6079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 608044f0eee88ff00398ff7f715fab053374d808c90dSteve Block double source_size_in_kb = static_cast<double>(source_size_) / 1024; 608144f0eee88ff00398ff7f715fab053374d808c90dSteve Block double normalized_time = source_size_in_kb > 0 608244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? (static_cast<double>(sum) / 1000) / source_size_in_kb 608344f0eee88ff00398ff7f715fab053374d808c90dSteve Block : 0; 608444f0eee88ff00398ff7f715fab053374d808c90dSteve Block double normalized_bytes = source_size_in_kb > 0 608544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ? total_size_ / source_size_in_kb 608644f0eee88ff00398ff7f715fab053374d808c90dSteve Block : 0; 608744f0eee88ff00398ff7f715fab053374d808c90dSteve Block PrintF("%30s - %7.3f ms %7.3f bytes\n", "Sum", 608844f0eee88ff00398ff7f715fab053374d808c90dSteve Block normalized_time, normalized_bytes); 6089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("---------------------------------------------------------------\n"); 6090b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch PrintF("%30s - %7.3f ms (%.1f times slower than full code gen)\n", 6091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "Total", 6092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<double>(total_) / 1000, 6093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<double>(total_) / full_code_gen_); 6094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6097b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdochvoid HStatistics::SaveTiming(const char* name, int64_t ticks, unsigned size) { 6098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (name == HPhase::kFullCodeGen) { 6099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch full_code_gen_ += ticks; 6100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (name == HPhase::kTotal) { 6101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch total_ += ticks; 6102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 6103b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch total_size_ += size; 6104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < names_.length(); ++i) { 6105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (names_[i] == name) { 6106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch timing_[i] += ticks; 6107b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch sizes_[i] += size; 6108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 6109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch names_.Add(name); 6112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch timing_.Add(ticks); 6113b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch sizes_.Add(size); 6114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kFullCodeGen = "Full code generator"; 6119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kTotal = "Total"; 6120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::Begin(const char* name, 6123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph, 6124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LChunk* chunk, 6125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LAllocator* allocator) { 6126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch name_ = name; 6127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_ = graph; 6128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk_ = chunk; 6129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch allocator_ = allocator; 6130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator != NULL && chunk_ == NULL) { 6131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk_ = allocator->chunk(); 6132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 613344f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_hydrogen_stats) start_ = OS::Ticks(); 6134b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch start_allocation_size_ = Zone::allocation_size_; 6135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::End() const { 613944f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (FLAG_hydrogen_stats) { 6140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int64_t end = OS::Ticks(); 6141b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch unsigned size = Zone::allocation_size_ - start_allocation_size_; 6142b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch HStatistics::Instance()->SaveTiming(name_, end - start_, size); 6143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_hydrogen) { 6146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_); 6147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_); 6148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator_ != NULL) { 6149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HTracer::Instance()->TraceLiveRanges(name_, allocator_); 6150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 6152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 6154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (graph_ != NULL) graph_->Verify(); 6155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator_ != NULL) allocator_->Verify(); 6156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 6157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 6158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 6159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} } // namespace v8::internal 6160