hydrogen.cc revision 086aeeaae12517475c22695a200be45495516549
1b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Copyright 2010 the V8 project authors. All rights reserved. 2b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Redistribution and use in source and binary forms, with or without 3b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// modification, are permitted provided that the following conditions are 4b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// met: 5b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 6b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Redistributions of source code must retain the above copyright 7b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// notice, this list of conditions and the following disclaimer. 8b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Redistributions in binary form must reproduce the above 9b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// copyright notice, this list of conditions and the following 10b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// disclaimer in the documentation and/or other materials provided 11b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// with the distribution. 12b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// * Neither the name of Google Inc. nor the names of its 13b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// contributors may be used to endorse or promote products derived 14b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from this software without specific prior written permission. 15b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 16b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 28b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hydrogen.h" 29b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 30b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "codegen.h" 31b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "data-flow.h" 32b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "full-codegen.h" 33b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "hashmap.h" 34b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "lithium-allocator.h" 35b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "parser.h" 36b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "scopes.h" 37b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 38b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#if V8_TARGET_ARCH_IA32 39b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "ia32/lithium-codegen-ia32.h" 40b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#elif V8_TARGET_ARCH_X64 41b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "x64/lithium-codegen-x64.h" 42b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#elif V8_TARGET_ARCH_ARM 43b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#include "arm/lithium-codegen-arm.h" 44b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#else 45b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#error Unsupported target architecture. 46b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 47b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 48b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace v8 { 49b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochnamespace internal { 50b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 51b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock::HBasicBlock(HGraph* graph) 52b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : block_id_(graph->GetNextBlockID()), 53b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_(graph), 54b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_(4), 55b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first_(NULL), 56b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_(NULL), 57b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch end_(NULL), 58b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_information_(NULL), 59b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch predecessors_(2), 60b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_(NULL), 61b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominated_blocks_(4), 62b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_environment_(NULL), 63b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch argument_count_(-1), 64b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first_instruction_index_(-1), 65b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_instruction_index_(-1), 66b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch deleted_phis_(4), 67b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch is_inline_return_target_(false) { 68b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 69b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 70b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 71b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AttachLoopInformation() { 72b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsLoopHeader()); 73b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_information_ = new HLoopInformation(this); 74b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 75b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 76b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 77b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::DetachLoopInformation() { 78b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsLoopHeader()); 79b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_information_ = NULL; 80b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 81b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 82b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 83b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddPhi(HPhi* phi) { 84b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsStartBlock()); 85b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_.Add(phi); 86b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->SetBlock(this); 87b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 88b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 89b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 90b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RemovePhi(HPhi* phi) { 91b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->block() == this); 92b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phis_.Contains(phi)); 93b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->HasNoUses()); 94b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->ClearOperands(); 95b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_.RemoveElement(phi); 96b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->SetBlock(NULL); 97b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 98b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 99b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddInstruction(HInstruction* instr) { 101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsStartBlock() || !IsFinished()); 102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!instr->IsLinked()); 103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsFinished()); 104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first_ == NULL) { 105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBlockEntry* entry = new HBlockEntry(); 106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch entry->InitializeAsFirst(this); 107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first_ = entry; 108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->InsertAfter(GetLastInstruction()); 110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HBasicBlock::GetLastInstruction() { 114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (end_ != NULL) return end_->previous(); 115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first_ == NULL) return NULL; 116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (last_ == NULL) last_ = first_; 117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (last_->next() != NULL) last_ = last_->next(); 118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return last_; 119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSimulate* HBasicBlock::CreateSimulate(int id) { 123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(HasEnvironment()); 124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* environment = last_environment(); 125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(id == AstNode::kNoNumber || 126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment->closure()->shared()->VerifyBailoutId(id)); 127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int push_count = environment->push_count(); 129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int pop_count = environment->pop_count(); 130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int length = environment->length(); 132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSimulate* instr = new HSimulate(id, pop_count, length); 133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = push_count - 1; i >= 0; --i) { 134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->AddPushedValue(environment->ExpressionStackAt(i)); 135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < environment->assigned_variables()->length(); ++i) { 137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = environment->assigned_variables()->at(i); 138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->AddAssignedValue(index, environment->Lookup(index)); 139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment->ClearHistory(); 141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Finish(HControlInstruction* end) { 146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsFinished()); 147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(end); 148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch end_ = end; 149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (end->FirstSuccessor() != NULL) { 150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch end->FirstSuccessor()->RegisterPredecessor(this); 151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (end->SecondSuccessor() != NULL) { 152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch end->SecondSuccessor()->RegisterPredecessor(this); 153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Goto(HBasicBlock* block, bool include_stack_check) { 159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(AstNode::kNoNumber); 160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGoto* instr = new HGoto(block); 161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_include_stack_check(include_stack_check); 162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Finish(instr); 163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::SetInitialEnvironment(HEnvironment* env) { 167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!HasEnvironment()); 168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(first() == NULL); 169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UpdateEnvironment(env); 170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::SetJoinId(int id) { 174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = predecessors_.length(); 175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(length > 0); 176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; i++) { 177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* predecessor = predecessors_[i]; 178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(predecessor->end()->IsGoto()); 179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSimulate* simulate = HSimulate::cast(predecessor->GetLastInstruction()); 180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We only need to verify the ID once. 181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(i != 0 || 182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch predecessor->last_environment()->closure()->shared() 183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ->VerifyBailoutId(id)); 184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch simulate->set_ast_id(id); 185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HBasicBlock::Dominates(HBasicBlock* other) const { 190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* current = other->dominator(); 191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current == this) return true; 193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->dominator(); 194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) { 200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsLoopHeader()); 201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetJoinId(stmt->EntryId()); 203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (predecessors()->length() == 1) { 204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // This is a degenerated loop. 205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DetachLoopInformation(); 206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only the first entry into the loop is from outside the loop. All other 210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // entries must be back edges. 211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 1; i < predecessors()->length(); ++i) { 212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_information()->RegisterBackEdge(predecessors()->at(i)); 213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::RegisterPredecessor(HBasicBlock* pred) { 218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!predecessors_.is_empty()) { 219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only loop header blocks can have a predecessor added after 220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // instructions have been added to the block (they have phis for all 221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // values in the environment, these phis may be eliminated later). 222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsLoopHeader() || first_ == NULL); 223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* incoming_env = pred->last_environment(); 224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (IsLoopHeader()) { 2259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(phis()->length() == incoming_env->length()); 226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phis_.length(); ++i) { 227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis_[i]->AddInput(incoming_env->values()->at(i)); 228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_environment()->AddIncomingEdge(this, pred->last_environment()); 231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (!HasEnvironment() && !IsFinished()) { 233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!IsLoopHeader()); 234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetInitialEnvironment(pred->last_environment()->Copy()); 235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch predecessors_.Add(pred); 238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddDominatedBlock(HBasicBlock* block) { 242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!dominated_blocks_.Contains(block)); 243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keep the list of dominated blocks sorted such that if there is two 244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // succeeding block in this list, the predecessor is before the successor. 245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = 0; 246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (index < dominated_blocks_.length() && 247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominated_blocks_[index]->block_id() < block->block_id()) { 248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ++index; 249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominated_blocks_.InsertAt(index, block); 251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AssignCommonDominator(HBasicBlock* other) { 255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (dominator_ == NULL) { 256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_ = other; 257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->AddDominatedBlock(this); 258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (other->dominator() != NULL) { 259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* first = dominator_; 260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* second = other; 261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (first != second) { 263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first->block_id() > second->block_id()) { 264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first = first->dominator(); 265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch second = second->dominator(); 267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(first != NULL && second != NULL); 269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (dominator_ != first) { 272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(dominator_->dominated_blocks_.Contains(this)); 273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_->dominated_blocks_.RemoveElement(this); 274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator_ = first; 275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch first->AddDominatedBlock(this); 276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const { 282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < predecessors_.length(); ++i) { 283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (predecessors_[i] == predecessor) return i; 284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return -1; 287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::Verify() { 292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that every block is finished. 293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(IsFinished()); 294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(block_id() >= 0); 295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Verify that all blocks targetting a branch target, have the same boolean 297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // value on top of their expression stack. 298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!cond().is_null()) { 299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(predecessors()->length() > 0); 300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 1; i < predecessors()->length(); i++) { 301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* pred = predecessors()->at(i); 302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* top = pred->last_environment()->Top(); 303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(top->IsConstant()); 304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Object* a = *HConstant::cast(top)->handle(); 305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Object* b = *cond(); 306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(a == b); 307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::RegisterBackEdge(HBasicBlock* block) { 314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch this->back_edges_.Add(block); 315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddBlock(block); 316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HLoopInformation::GetLastBackEdge() const { 320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int max_id = -1; 321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* result = NULL; 322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < back_edges_.length(); ++i) { 323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* cur = back_edges_[i]; 324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (cur->block_id() > max_id) { 325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch max_id = cur->block_id(); 326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = cur; 327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HLoopInformation::AddBlock(HBasicBlock* block) { 334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block == loop_header()) return; 335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->parent_loop_header() == loop_header()) return; 336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->parent_loop_header() != NULL) { 337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddBlock(block->parent_loop_header()); 338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->set_parent_loop_header(loop_header()); 340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.Add(block); 341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < block->predecessors()->length(); ++i) { 342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddBlock(block->predecessors()->at(i)); 343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Checks reachability of the blocks in this graph and stores a bit in 351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the BitVector "reachable()" for every block that can be reached 352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// from the start block of the graph. If "dont_visit" is non-null, the given 353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// block is treated as if it would not be part of the graph. "visited_count()" 354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// returns the number of reachable blocks. 355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass ReachabilityAnalyzer BASE_EMBEDDED { 356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ReachabilityAnalyzer(HBasicBlock* entry_block, 358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int block_count, 359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dont_visit) 360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : visited_count_(0), 361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stack_(16), 362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reachable_(block_count), 363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dont_visit_(dont_visit) { 364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushBlock(entry_block); 365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Analyze(); 366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int visited_count() const { return visited_count_; } 369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const BitVector* reachable() const { return &reachable_; } 370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void PushBlock(HBasicBlock* block) { 373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block != NULL && block != dont_visit_ && 374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !reachable_.Contains(block->block_id())) { 375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch reachable_.Add(block->block_id()); 376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stack_.Add(block); 377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visited_count_++; 378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze() { 382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!stack_.is_empty()) { 383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HControlInstruction* end = stack_.RemoveLast()->end(); 384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushBlock(end->FirstSuccessor()); 385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushBlock(end->SecondSuccessor()); 386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int visited_count_; 390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*> stack_; 391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector reachable_; 392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dont_visit_; 393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Verify() const { 397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); i++) { 398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = blocks_.at(i); 399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->Verify(); 401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that every block contains at least one node and that only the last 403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // node is a control instruction. 404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = block->first(); 405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current != NULL && current->IsBlockEntry()); 406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT((current->next() == NULL) == current->IsControlInstruction()); 408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current->block() == block); 409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->Verify(); 410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that successors are correctly set. 414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* first = block->end()->FirstSuccessor(); 415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* second = block->end()->SecondSuccessor(); 416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(second == NULL || first != NULL); 417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that the predecessor array is correct. 419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first != NULL) { 420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(first->predecessors()->Contains(block)); 421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (second != NULL) { 422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(second->predecessors()->Contains(block)); 423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that phis have correct arguments. 427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < block->phis()->length(); j++) { 428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = block->phis()->at(j); 429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->Verify(); 430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that all join blocks have predecessors that end with an 433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // unconditional goto and agree on their environment node id. 434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->predecessors()->length() >= 2) { 435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int id = block->predecessors()->first()->last_environment()->ast_id(); 436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int k = 0; k < block->predecessors()->length(); k++) { 437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* predecessor = block->predecessors()->at(k); 438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(predecessor->end()->IsGoto()); 439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(predecessor->last_environment()->ast_id() == id); 440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check special property of first block to have no predecessors. 445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(blocks_.at(0)->predecessors()->is_empty()); 446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that the graph is fully connected. 448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL); 449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(analyzer.visited_count() == blocks_.length()); 450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check that entry block dominator is NULL. 452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(entry_block_->dominator() == NULL); 453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check dominators. 455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = blocks_.at(i); 457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->dominator() == NULL) { 458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only start block may have no dominator assigned to. 459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(i == 0); 460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Assert that block is unreachable if dominator must not be visited. 462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ReachabilityAnalyzer dominator_analyzer(entry_block_, 463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.length(), 464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->dominator()); 465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!dominator_analyzer.reachable()->Contains(block->block_id())); 466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer, 474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Object* value) { 475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!pointer->is_set()) { 476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* constant = new HConstant(Handle<Object>(value), 477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation::Tagged()); 478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch constant->InsertAfter(GetConstantUndefined()); 479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pointer->set(constant); 480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return pointer->get(); 482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstant1() { 486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return GetConstant(&constant_1_, Smi::FromInt(1)); 487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantMinus1() { 491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return GetConstant(&constant_minus1_, Smi::FromInt(-1)); 492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantTrue() { 496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return GetConstant(&constant_true_, Heap::true_value()); 497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHConstant* HGraph::GetConstantFalse() { 501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return GetConstant(&constant_false_, Heap::false_value()); 502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::AppendOptional(HSubgraph* graph, 506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool on_true_branch, 507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* boolean_value) { 508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(HasExit() && graph->HasExit()); 509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* other_block = graph_->CreateBasicBlock(); 510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* join_block = graph_->CreateBasicBlock(); 511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* true_branch = other_block; 513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* false_branch = graph->entry_block(); 514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (on_true_branch) { 515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_branch = graph->entry_block(); 516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_branch = other_block; 517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_->Finish(new HBranch(true_branch, false_branch, boolean_value)); 520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other_block->Goto(join_block); 521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph->exit_block()->Goto(join_block); 522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = join_block; 523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::AppendJoin(HSubgraph* then_graph, 527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* else_graph, 528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AstNode* node) { 529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (then_graph->HasExit() && else_graph->HasExit()) { 530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We need to merge, create new merge block. 531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* join_block = graph_->CreateBasicBlock(); 532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch then_graph->exit_block()->Goto(join_block); 533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else_graph->exit_block()->Goto(join_block); 534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch join_block->SetJoinId(node->id()); 535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = join_block; 536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (then_graph->HasExit()) { 537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = then_graph->exit_block_; 538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (else_graph->HasExit()) { 539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = else_graph->exit_block_; 540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = NULL; 542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::ResolveContinue(IterationStatement* statement) { 547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* continue_block = BundleContinue(statement); 548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (continue_block != NULL) { 549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = JoinBlocks(exit_block(), 550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch continue_block, 551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch statement->ContinueId()); 552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HSubgraph::BundleBreak(BreakableStatement* statement) { 557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return BundleBreakContinue(statement, false, statement->ExitId()); 558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HSubgraph::BundleContinue(IterationStatement* statement) { 562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return BundleBreakContinue(statement, true, statement->ContinueId()); 563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HSubgraph::BundleBreakContinue(BreakableStatement* statement, 567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_continue, 568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int join_id) { 569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* result = NULL; 570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<BreakContinueInfo*>* infos = break_continue_info(); 571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < infos->length(); ++i) { 572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BreakContinueInfo* info = infos->at(i); 573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info->is_continue() == is_continue && 574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch info->target() == statement && 575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !info->IsResolved()) { 576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (result == NULL) { 577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = graph_->CreateBasicBlock(); 578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch info->block()->Goto(result); 580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch info->Resolve(); 581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (result != NULL) result->SetJoinId(join_id); 585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HSubgraph::JoinBlocks(HBasicBlock* a, HBasicBlock* b, int id) { 591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (a == NULL) return b; 592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (b == NULL) return a; 593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* target = graph_->CreateBasicBlock(); 594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch a->Goto(target); 595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch b->Goto(target); 596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch target->SetJoinId(id); 597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return target; 598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::AppendEndless(HSubgraph* body, IterationStatement* statement) { 602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ConnectExitTo(body->entry_block()); 603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->ResolveContinue(statement); 604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->ConnectExitTo(body->entry_block(), true); 605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = body->BundleBreak(statement); 606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->entry_block()->PostProcessLoopHeader(statement); 607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::AppendDoWhile(HSubgraph* body, 611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch IterationStatement* statement, 612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* go_back, 613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* exit) { 614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ConnectExitTo(body->entry_block()); 615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch go_back->ConnectExitTo(body->entry_block(), true); 616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* break_block = body->BundleBreak(statement); 618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = 619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); 620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->entry_block()->PostProcessLoopHeader(statement); 621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::AppendWhile(HSubgraph* condition, 625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* body, 626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch IterationStatement* statement, 627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* continue_subgraph, 628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* exit) { 629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ConnectExitTo(condition->entry_block()); 630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* break_block = body->BundleBreak(statement); 632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = 633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch JoinBlocks(exit->exit_block(), break_block, statement->ExitId()); 634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (continue_subgraph != NULL) { 636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->ConnectExitTo(continue_subgraph->entry_block(), true); 637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch continue_subgraph->entry_block()->SetJoinId(statement->EntryId()); 638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = JoinBlocks(exit_block_, 639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch continue_subgraph->exit_block(), 640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch statement->ExitId()); 641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->ConnectExitTo(condition->entry_block(), true); 643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch condition->entry_block()->PostProcessLoopHeader(statement); 645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::Append(HSubgraph* next, BreakableStatement* stmt) { 649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_->Goto(next->entry_block()); 650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = next->exit_block_; 651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt != NULL) { 653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next->entry_block()->SetJoinId(stmt->EntryId()); 654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* break_block = next->BundleBreak(stmt); 655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = JoinBlocks(exit_block(), break_block, stmt->ExitId()); 656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::FinishExit(HControlInstruction* instruction) { 661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(HasExit()); 662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_->Finish(instruction); 663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_->ClearEnvironment(); 664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = NULL; 665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::FinishBreakContinue(BreakableStatement* target, 669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_continue) { 670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!exit_block_->IsFinished()); 671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BreakContinueInfo* info = new BreakContinueInfo(target, exit_block_, 672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch is_continue); 673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break_continue_info_.Add(info); 674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block_ = NULL; 675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHGraph::HGraph(CompilationInfo* info) 679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : HSubgraph(this), 680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next_block_id_(0), 681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch info_(info), 682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_(8), 683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_(16), 684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi_list_(NULL) { 685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch start_environment_ = new HEnvironment(NULL, info->scope(), info->closure()); 686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch start_environment_->set_ast_id(info->function()->id()); 687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHandle<Code> HGraph::Compile() { 691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int values = GetMaximumValueID(); 692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (values > LAllocator::max_initial_value_ids()) { 693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_bailout) PrintF("Function is too big\n"); 694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Handle<Code>::null(); 695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LAllocator allocator(values, this); 698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LChunkBuilder builder(this, &allocator); 699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LChunk* chunk = builder.Build(); 700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk == NULL) return Handle<Code>::null(); 701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!FLAG_alloc_lithium) return Handle<Code>::null(); 703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch allocator.Allocate(chunk); 705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!FLAG_use_lithium) return Handle<Code>::null(); 707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch MacroAssembler assembler(NULL, 0); 709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LCodeGen generator(chunk, &assembler, info()); 710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_eliminate_empty_blocks) { 712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk->MarkEmptyBlocks(); 713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (generator.GenerateCode()) { 716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_codegen) { 717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Crankshaft Compiler - "); 718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CodeGenerator::MakeCodePrologue(info()); 720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Code::Flags flags = 721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Code::ComputeFlags(Code::OPTIMIZED_FUNCTION, NOT_IN_LOOP); 722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Code> code = 723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CodeGenerator::MakeCodeEpilogue(&assembler, flags, info()); 724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch generator.FinishCode(code); 725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CodeGenerator::PrintCode(code, info()); 726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return code; 727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Handle<Code>::null(); 729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraph::CreateBasicBlock() { 733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* result = new HBasicBlock(this); 734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.Add(result); 735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Canonicalize() { 740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Canonicalize", this); 741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_use_canonicalizing) { 742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks()->length(); ++i) { 743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* b = blocks()->at(i); 744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (HInstruction* insn = b->first(); insn != NULL; insn = insn->next()) { 745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = insn->Canonicalize(); 746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != insn) { 747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != NULL) { 748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch insn->ReplaceAndDelete(value); 749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch insn->Delete(); 751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::OrderBlocks() { 760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Block ordering"); 761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector visited(blocks_.length()); 762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*> reverse_result(8); 764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* start = blocks_[0]; 765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(start, &visited, &reverse_result, NULL); 766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.Clear(); 768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = 0; 769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = reverse_result.length() - 1; i >= 0; --i) { 770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* b = reverse_result[i]; 771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_.Add(b); 772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch b->set_block_id(index++); 773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PostorderLoopBlocks(HLoopInformation* loop, 778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector* visited, 779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*>* order, 780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header) { 781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < loop->blocks()->length(); ++i) { 782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* b = loop->blocks()->at(i); 783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(b->end()->SecondSuccessor(), visited, order, loop_header); 784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(b->end()->FirstSuccessor(), visited, order, loop_header); 785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (b->IsLoopHeader() && b != loop->loop_header()) { 786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PostorderLoopBlocks(b->loop_information(), visited, order, loop_header); 787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::Postorder(HBasicBlock* block, 793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector* visited, 794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HBasicBlock*>* order, 795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header) { 796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block == NULL || visited->Contains(block->block_id())) return; 797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->parent_loop_header() != loop_header) return; 798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visited->Add(block->block_id()); 799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PostorderLoopBlocks(block->loop_information(), visited, order, loop_header); 801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(block->end()->SecondSuccessor(), visited, order, block); 802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(block->end()->FirstSuccessor(), visited, order, block); 803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(block->end()->SecondSuccessor(), visited, order, loop_header); 805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Postorder(block->end()->FirstSuccessor(), visited, order, loop_header); 806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(block->end()->FirstSuccessor() == NULL || 808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch order->Contains(block->end()->FirstSuccessor()) || 809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->end()->FirstSuccessor()->IsLoopHeader()); 810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(block->end()->SecondSuccessor() == NULL || 811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch order->Contains(block->end()->SecondSuccessor()) || 812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->end()->SecondSuccessor()->IsLoopHeader()); 813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch order->Add(block); 814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::AssignDominators() { 818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Assign dominators", this); 819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (blocks_[i]->IsLoopHeader()) { 821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->first()); 822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < blocks_[i]->predecessors()->length(); ++j) { 824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j)); 825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::EliminateRedundantPhis() { 832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Phi elimination", this); 833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> uses_to_replace(2); 834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Worklist of phis that can potentially be eliminated. Initialized 836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // with all phi nodes. When elimination of a phi node modifies 837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // another phi node the modified phi node is added to the worklist. 838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HPhi*> worklist(blocks_.length()); 839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist.AddAll(*blocks_[i]->phis()); 841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!worklist.is_empty()) { 844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = worklist.RemoveLast(); 845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = phi->block(); 846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Skip phi node if it was already replaced. 848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block == NULL) continue; 849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get replacement value if phi is redundant. 851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = phi->GetRedundantReplacement(); 852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != NULL) { 854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Iterate through uses finding the ones that should be 855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // replaced. 856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HValue*>* uses = phi->uses(); 857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < uses->length(); ++i) { 858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = uses->at(i); 859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!use->block()->IsStartBlock()) { 860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uses_to_replace.Add(use); 861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Replace the uses and add phis modified to the work list. 864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < uses_to_replace.length(); ++i) { 865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = uses_to_replace[i]; 866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->ReplaceAtUse(use, value); 867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (use->IsPhi()) worklist.Add(HPhi::cast(use)); 868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uses_to_replace.Rewind(0); 870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->RemovePhi(phi); 871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (phi->HasNoUses() && 872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !phi->HasReceiverOperand() && 873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FLAG_eliminate_dead_phis) { 874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We can't eliminate phis that have the receiver as an operand 875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // because in case of throwing an error we need the correct 876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // receiver value in the environment to construct a corrent 877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // stack trace. 878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->RemovePhi(phi); 879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->RecordDeletedPhi(phi->merged_index()); 880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraph::CollectPhis() { 886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HBasicBlock*>* blocks = graph_->blocks(); 887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi_list_ = new ZoneList<HPhi*>(blocks->length()); 888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks->length(); ++i) { 889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < blocks->at(i)->phis()->length(); j++) { 890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = blocks->at(i)->phis()->at(j); 891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi_list_->Add(phi); 892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't support phi uses of arguments for now. 893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (phi->CheckFlag(HValue::kIsArguments)) return false; 894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InferTypes(ZoneList<HValue*>* worklist) { 901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector in_worklist(GetMaximumValueID()); 902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < worklist->length(); ++i) { 903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!in_worklist.Contains(worklist->at(i)->id())); 904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist.Add(worklist->at(i)->id()); 905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!worklist->is_empty()) { 908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* current = worklist->RemoveLast(); 909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist.Remove(current->id()); 910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->UpdateInferredType()) { 911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < current->uses()->length(); j++) { 912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = current->uses()->at(j); 913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!in_worklist.Contains(use->id())) { 914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist.Add(use->id()); 915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist->Add(use); 916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HRangeAnalysis BASE_EMBEDDED { 924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit HRangeAnalysis(HGraph* graph) : graph_(graph), changed_ranges_(16) {} 926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(); 928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void TraceRange(const char* msg, ...); 931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(HBasicBlock* block); 932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferControlFlowRange(HBranch* branch, HBasicBlock* dest); 933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferControlFlowRange(Token::Value op, HValue* value, HValue* other); 934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferPhiRange(HPhi* phi); 935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferRange(HValue* value); 936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void RollBackTo(int index); 937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AddRange(HValue* value, Range* range); 938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> changed_ranges_; 941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::TraceRange(const char* msg, ...) { 945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_range) { 946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_list arguments; 947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_start(arguments, msg); 948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch OS::VPrint(msg, arguments); 949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_end(arguments); 950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze() { 955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Range analysis", graph_); 956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Analyze(graph_->blocks()->at(0)); 957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::Analyze(HBasicBlock* block) { 961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Analyzing block B%d\n", block->block_id()); 962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_changed_range = changed_ranges_.length() - 1; 964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Infer range based on control flow. 966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->predecessors()->length() == 1) { 967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* pred = block->predecessors()->first(); 968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (pred->end()->IsBranch()) { 969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferControlFlowRange(HBranch::cast(pred->end()), block); 970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Process phi instructions. 974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < block->phis()->length(); ++i) { 975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = block->phis()->at(i); 976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferPhiRange(phi); 977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Go through all instructions of the current block. 980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != block->end()) { 982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferRange(instr); 983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Continue analysis in all dominated blocks. 987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < block->dominated_blocks()->length(); ++i) { 988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Analyze(block->dominated_blocks()->at(i)); 989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RollBackTo(last_changed_range); 992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferControlFlowRange(HBranch* branch, HBasicBlock* dest) { 996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(branch->FirstSuccessor() == dest || branch->SecondSuccessor() == dest); 997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(branch->FirstSuccessor() != dest || branch->SecondSuccessor() != dest); 998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (branch->value()->IsCompare()) { 1000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCompare* compare = HCompare::cast(branch->value()); 1001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Value op = compare->token(); 1002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (branch->SecondSuccessor() == dest) { 1003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch op = Token::NegateCompareOp(op); 1004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Value inverted_op = Token::InvertCompareOp(op); 1006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferControlFlowRange(op, compare->left(), compare->right()); 1007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferControlFlowRange(inverted_op, compare->right(), compare->left()); 1008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// We know that value [op] other. Use this information to update the range on 1013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// value. 1014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferControlFlowRange(Token::Value op, 1015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 1016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* other) { 1017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* range = other->range(); 1018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range == NULL) range = new Range(); 1019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* new_range = NULL; 1020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Control flow range infer %d %s %d\n", 1022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->id(), 1023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Name(op), 1024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->id()); 1025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::EQ || op == Token::EQ_STRICT) { 1027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The same range has to apply for value. 1028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range = range->Copy(); 1029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::LT || op == Token::LTE) { 1030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range = range->CopyClearLower(); 1031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::LT) { 1032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->AddConstant(-1); 1033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::GT || op == Token::GTE) { 1035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range = range->CopyClearUpper(); 1036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::GT) { 1037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->AddConstant(1); 1038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (new_range != NULL && !new_range->IsMostGeneric()) { 1042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddRange(value, new_range); 1043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferPhiRange(HPhi* phi) { 1048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(twuerthinger): Infer loop phi ranges. 1049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferRange(phi); 1050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::InferRange(HValue* value) { 1054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!value->HasRange()); 1055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!value->representation().IsNone()) { 1056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->ComputeInitialRange(); 1057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* range = value->range(); 1058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Initial inferred range of %d (%s) set to [%d,%d]\n", 1059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->id(), 1060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->Mnemonic(), 1061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->lower(), 1062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->upper()); 1063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::RollBackTo(int index) { 1068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = index + 1; i < changed_ranges_.length(); ++i) { 1069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch changed_ranges_[i]->RemoveLastAddedRange(); 1070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch changed_ranges_.Rewind(index + 1); 1072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HRangeAnalysis::AddRange(HValue* value, Range* range) { 1076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* original_range = value->range(); 1077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->AddNewRange(range); 1078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch changed_ranges_.Add(value); 1079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Range* new_range = value->range(); 1080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Updated range of %d set to [%d,%d]\n", 1081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->id(), 1082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->lower(), 1083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_range->upper()); 1084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (original_range != NULL) { 1085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("Original range was [%d,%d]\n", 1086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch original_range->lower(), 1087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch original_range->upper()); 1088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceRange("New information was [%d,%d]\n", 1090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->lower(), 1091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch range->upper()); 1092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TraceGVN(const char* msg, ...) { 1096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_gvn) { 1097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_list arguments; 1098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_start(arguments, msg); 1099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch OS::VPrint(msg, arguments); 1100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch va_end(arguments); 1101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValueMap::HValueMap(const HValueMap* other) 1106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : array_size_(other->array_size_), 1107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_size_(other->lists_size_), 1108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_(other->count_), 1109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch present_flags_(other->present_flags_), 1110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_(Zone::NewArray<HValueMapListElement>(other->array_size_)), 1111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_(Zone::NewArray<HValueMapListElement>(other->lists_size_)), 1112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_(other->free_list_head_) { 1113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(array_, other->array_, array_size_ * sizeof(HValueMapListElement)); 1114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(lists_, other->lists_, lists_size_ * sizeof(HValueMapListElement)); 1115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Kill(int flags) { 1119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int depends_flags = HValue::ConvertChangesToDependsFlags(flags); 1120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ((present_flags_ & depends_flags) == 0) return; 1121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch present_flags_ = 0; 1122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < array_size_; ++i) { 1123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = array_[i].value; 1124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != NULL) { 1125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Clear list of collisions first, so we know if it becomes empty. 1126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int kept = kNil; // List of kept elements. 1127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next; 1128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int current = array_[i].next; current != kNil; current = next) { 1129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next = lists_[current].next; 1130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ((lists_[current].value->flags() & depends_flags) != 0) { 1131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop it. 1132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_--; 1133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[current].next = free_list_head_; 1134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = current; 1135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keep it. 1137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[current].next = kept; 1138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch kept = current; 1139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch present_flags_ |= lists_[current].value->flags(); 1140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].next = kept; 1143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Now possibly drop directly indexed element. 1145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ((array_[i].value->flags() & depends_flags) != 0) { // Drop it. 1146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_--; 1147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int head = array_[i].next; 1148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (head == kNil) { 1149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].value = NULL; 1150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].value = lists_[head].value; 1152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[i].next = lists_[head].next; 1153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[head].next = free_list_head_; 1154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = head; 1155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch present_flags_ |= array_[i].value->flags(); // Keep it. 1158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValue* HValueMap::Lookup(HValue* value) const { 1165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t hash = static_cast<uint32_t>(value->Hashcode()); 1166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t pos = Bound(hash); 1167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (array_[pos].value != NULL) { 1168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (array_[pos].value->Equals(value)) return array_[pos].value; 1169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next = array_[pos].next; 1170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (next != kNil) { 1171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lists_[next].value->Equals(value)) return lists_[next].value; 1172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next = lists_[next].next; 1173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return NULL; 1176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Resize(int new_size) { 1180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(new_size > count_); 1181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Hashing the values into the new array has no more collisions than in the 1182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // old hash map, so we can use the existing lists_ array, if we are careful. 1183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Make sure we have at least one free element. 1185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (free_list_head_ == kNil) { 1186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ResizeLists(lists_size_ << 1); 1187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* new_array = 1190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Zone::NewArray<HValueMapListElement>(new_size); 1191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memset(new_array, 0, sizeof(HValueMapListElement) * new_size); 1192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* old_array = array_; 1194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int old_size = array_size_; 1195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int old_count = count_; 1197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_ = 0; 1198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do not modify present_flags_. It is currently correct. 1199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_size_ = new_size; 1200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_ = new_array; 1201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (old_array != NULL) { 1203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Iterate over all the elements in lists, rehashing them. 1204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < old_size; ++i) { 1205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (old_array[i].value != NULL) { 1206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int current = old_array[i].next; 1207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != kNil) { 1208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Insert(lists_[current].value); 1209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int next = lists_[current].next; 1210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[current].next = free_list_head_; 1211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = current; 1212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = next; 1213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Rehash the directly stored value. 1215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Insert(old_array[i].value); 1216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch USE(old_count); 1220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(count_ == old_count); 1221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::ResizeLists(int new_size) { 1225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(new_size > lists_size_); 1226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* new_lists = 1228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Zone::NewArray<HValueMapListElement>(new_size); 1229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memset(new_lists, 0, sizeof(HValueMapListElement) * new_size); 1230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMapListElement* old_lists = lists_; 1232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int old_size = lists_size_; 1233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_size_ = new_size; 1235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_ = new_lists; 1236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (old_lists != NULL) { 1238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch memcpy(lists_, old_lists, old_size * sizeof(HValueMapListElement)); 1239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = old_size; i < lists_size_; ++i) { 1241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[i].next = free_list_head_; 1242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = i; 1243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HValueMap::Insert(HValue* value) { 1248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(value != NULL); 1249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Resizing when half of the hashtable is filled up. 1250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (count_ >= array_size_ >> 1) Resize(array_size_ << 1); 1251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(count_ < array_size_); 1252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch count_++; 1253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch uint32_t pos = Bound(static_cast<uint32_t>(value->Hashcode())); 1254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (array_[pos].value == NULL) { 1255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[pos].value = value; 1256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[pos].next = kNil; 1257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (free_list_head_ == kNil) { 1259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ResizeLists(lists_size_ << 1); 1260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int new_element_pos = free_list_head_; 1262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(new_element_pos != kNil); 1263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch free_list_head_ = lists_[free_list_head_].next; 1264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[new_element_pos].value = value; 1265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch lists_[new_element_pos].next = array_[pos].next; 1266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(array_[pos].next == kNil || lists_[array_[pos].next].value != NULL); 1267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch array_[pos].next = new_element_pos; 1268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HStackCheckEliminator BASE_EMBEDDED { 1273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 1274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { } 1275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Process(); 1277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void RemoveStackCheck(HBasicBlock* block); 1280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 1282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::Process() { 1286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For each loop block walk the dominator tree from the backwards branch to 1287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the loop header. If a call instruction is encountered the backwards branch 1288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // is dominated by a call and the stack check in the backwards branch can be 1289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // removed. 1290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < graph_->blocks()->length(); i++) { 1291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* back_edge = block->loop_information()->GetLastBackEdge(); 1294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dominator = back_edge; 1295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool back_edge_dominated_by_call = false; 1296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (dominator != block && !back_edge_dominated_by_call) { 1297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = dominator->first(); 1298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL && !back_edge_dominated_by_call) { 1299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->IsCall()) { 1300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch RemoveStackCheck(back_edge); 1301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch back_edge_dominated_by_call = true; 1302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 1304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch dominator = dominator->dominator(); 1306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStackCheckEliminator::RemoveStackCheck(HBasicBlock* block) { 1313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->IsGoto()) { 1316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGoto::cast(instr)->set_include_stack_check(false); 1317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 1318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 1320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HGlobalValueNumberer BASE_EMBEDDED { 1325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 1326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit HGlobalValueNumberer(HGraph* graph) 1327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : graph_(graph), 1328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block_side_effects_(graph_->blocks()->length()), 1329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_side_effects_(graph_->blocks()->length()) { 1330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(Heap::allow_allocation(false)); 1331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block_side_effects_.AddBlock(0, graph_->blocks()->length()); 1332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_side_effects_.AddBlock(0, graph_->blocks()->length()); 1333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ~HGlobalValueNumberer() { 1335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!Heap::allow_allocation(true)); 1336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(); 1339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AnalyzeBlock(HBasicBlock* block, HValueMap* map); 1342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void ComputeBlockSideEffects(); 1343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void LoopInvariantCodeMotion(); 1344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void ProcessLoopBlock(HBasicBlock* block, 1345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* before_loop, 1346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int loop_kills); 1347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool ShouldMove(HInstruction* instr, HBasicBlock* loop_header); 1348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 1350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A map of block IDs to their side effects. 1352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<int> block_side_effects_; 1353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A map of loop header block IDs to their loop's side effects. 1355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<int> loop_side_effects_; 1356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::Analyze() { 1360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ComputeBlockSideEffects(); 1361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_loop_invariant_code_motion) { 1362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LoopInvariantCodeMotion(); 1363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMap* map = new HValueMap(); 1365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AnalyzeBlock(graph_->blocks()->at(0), map); 1366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ComputeBlockSideEffects() { 1370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute side effects for the block. 1372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int id = block->block_id(); 1375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int side_effects = 0; 1376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch side_effects |= (instr->flags() & HValue::ChangesFlagsMask()); 1378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = instr->next(); 1379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block_side_effects_[id] |= side_effects; 1381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Loop headers are part of their loop. 1383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_side_effects_[id] |= side_effects; 1385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Propagate loop side effects upwards. 1388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->HasParentLoopHeader()) { 1389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int header_id = block->parent_loop_header()->block_id(); 1390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_side_effects_[header_id] |= 1391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->IsLoopHeader() ? loop_side_effects_[id] : side_effects; 1392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::LoopInvariantCodeMotion() { 1398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = graph_->blocks()->length() - 1; i >= 0; --i) { 1399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int side_effects = loop_side_effects_[block->block_id()]; 1402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Try loop invariant motion for block B%d effects=0x%x\n", 1403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->block_id(), 1404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch side_effects); 1405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* last = block->loop_information()->GetLastBackEdge(); 1407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = block->block_id(); j <= last->block_id(); ++j) { 1408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ProcessLoopBlock(graph_->blocks()->at(j), block, side_effects); 1409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::ProcessLoopBlock(HBasicBlock* block, 1416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header, 1417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int loop_kills) { 1418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* pre_header = loop_header->predecessors()->at(0); 1419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int depends_flags = HValue::ConvertChangesToDependsFlags(loop_kills); 1420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Loop invariant motion for B%d depends_flags=0x%x\n", 1421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->block_id(), 1422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch depends_flags); 1423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* next = instr->next(); 1426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->CheckFlag(HValue::kUseGVN) && 1427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (instr->flags() & depends_flags) == 0) { 1428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Checking instruction %d (%s)\n", 1429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->id(), 1430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->Mnemonic()); 1431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool inputs_loop_invariant = true; 1432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < instr->OperandCount(); ++i) { 1433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->OperandAt(i)->IsDefinedAfter(pre_header)) { 1434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inputs_loop_invariant = false; 1435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (inputs_loop_invariant && ShouldMove(instr, loop_header)) { 1439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Found loop invariant instruction %d\n", instr->id()); 1440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Move the instruction out of the loop. 1441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->Unlink(); 1442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->InsertBefore(pre_header->end()); 1443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = next; 1446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Only move instructions that postdominate the loop header (i.e. are 1450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// always executed inside the loop). This is to avoid unnecessary 1451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// deoptimizations assuming the loop is executed at least once. 1452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// TODO(fschneider): Better type feedback should give us information 1453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// about code that was never executed. 1454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGlobalValueNumberer::ShouldMove(HInstruction* instr, 1455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_header) { 1456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!instr->IsChange() && 1457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FLAG_aggressive_loop_invariant_motion) return true; 1458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = instr->block(); 1459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool result = true; 1460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block != loop_header) { 1461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 1; i < loop_header->predecessors()->length(); ++i) { 1462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool found = false; 1463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* pred = loop_header->predecessors()->at(i); 1464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (pred != loop_header) { 1465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (pred == block) found = true; 1466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pred = pred->dominator(); 1467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!found) { 1469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = false; 1470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 1475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) { 1479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Analyzing block B%d\n", block->block_id()); 1480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If this is a loop header kill everything killed by the loop. 1482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->Kill(loop_side_effects_[block->block_id()]); 1484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Go through all instructions of the current block. 1487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = block->first(); 1488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instr != NULL) { 1489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* next = instr->next(); 1490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int flags = (instr->flags() & HValue::ChangesFlagsMask()); 1491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (flags != 0) { 1492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!instr->CheckFlag(HValue::kUseGVN)); 1493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Clear all instructions in the map that are affected by side effects. 1494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->Kill(flags); 1495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Instruction %d kills\n", instr->id()); 1496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (instr->CheckFlag(HValue::kUseGVN)) { 1497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* other = map->Lookup(instr); 1498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (other != NULL) { 1499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(instr->Equals(other) && other->Equals(instr)); 1500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceGVN("Replacing value %d (%s) with value %d (%s)\n", 1501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->id(), 1502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->Mnemonic(), 1503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->id(), 1504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch other->Mnemonic()); 1505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->ReplaceValue(other); 1506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->Delete(); 1507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 1508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->Add(instr); 1509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = next; 1512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Recursively continue analysis for all immediately dominated blocks. 1515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = block->dominated_blocks()->length(); 1516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; ++i) { 1517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* dominated = block->dominated_blocks()->at(i); 1518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // No need to copy the map for the last child in the dominator tree. 1519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueMap* successor_map = (i == length - 1) ? map : map->Copy(); 1520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the dominated block is not a successor to this block we have to 1522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // kill everything killed on any path between this block and the 1523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // dominated block. Note we rely on the block ordering. 1524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_successor = false; 1525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int predecessor_count = dominated->predecessors()->length(); 1526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; !is_successor && j < predecessor_count; ++j) { 1527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch is_successor = (dominated->predecessors()->at(j) == block); 1528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!is_successor) { 1531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int side_effects = 0; 1532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = block->block_id() + 1; j < dominated->block_id(); ++j) { 1533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch side_effects |= block_side_effects_[j]; 1534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch successor_map->Kill(side_effects); 1536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AnalyzeBlock(dominated, successor_map); 1539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HInferRepresentation BASE_EMBEDDED { 1544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 1545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch explicit HInferRepresentation(HGraph* graph) 1546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : graph_(graph), worklist_(8), in_worklist_(graph->GetMaximumValueID()) {} 1547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void Analyze(); 1549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 1551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation TryChange(HValue* current); 1552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AddToWorklist(HValue* current); 1553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferBasedOnInputs(HValue* current); 1554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void AddDependantsToWorklist(HValue* current); 1555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch void InferBasedOnUses(HValue* current); 1556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph_; 1558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> worklist_; 1559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector in_worklist_; 1560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 1561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddToWorklist(HValue* current) { 1564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->representation().IsSpecialization()) return; 1565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!current->CheckFlag(HValue::kFlexibleRepresentation)) return; 1566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (in_worklist_.Contains(current->id())) return; 1567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist_.Add(current); 1568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist_.Add(current->id()); 1569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method tries to specialize the representation type of the value 1573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as a parameter. The value is asked to infer its representation type 1574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// based on its inputs. If the inferred type is more specialized, then this 1575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// becomes the new representation type of the node. 1576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnInputs(HValue* current) { 1577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation r = current->representation(); 1578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (r.IsSpecialization()) return; 1579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); 1580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation inferred = current->InferredRepresentation(); 1581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (inferred.IsSpecialization()) { 1582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->ChangeRepresentation(inferred); 1583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddDependantsToWorklist(current); 1584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::AddDependantsToWorklist(HValue* current) { 1589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < current->uses()->length(); ++i) { 1590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToWorklist(current->uses()->at(i)); 1591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < current->OperandCount(); ++i) { 1593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToWorklist(current->OperandAt(i)); 1594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// This method calculates whether specializing the representation of the value 1599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// given as the parameter has a benefit in terms of less necessary type 1600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// conversions. If there is a benefit, then the representation of the value is 1601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// specialized. 1602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::InferBasedOnUses(HValue* current) { 1603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation r = current->representation(); 1604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (r.IsSpecialization() || current->HasNoUses()) return; 1605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current->CheckFlag(HValue::kFlexibleRepresentation)); 1606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation new_rep = TryChange(current); 1607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!new_rep.IsNone()) { 1608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!current->representation().Equals(new_rep)) { 1609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->ChangeRepresentation(new_rep); 1610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddDependantsToWorklist(current); 1611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HInferRepresentation::TryChange(HValue* current) { 1617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Array of use counts for each representation. 1618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int use_count[Representation::kNumRepresentations]; 1619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < Representation::kNumRepresentations; i++) { 1620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch use_count[i] = 0; 1621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < current->uses()->length(); ++i) { 1624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = current->uses()->at(i); 1625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = use->LookupOperandIndex(0, current); 1626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation req_rep = use->RequiredInputRepresentation(index); 1627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (req_rep.IsNone()) continue; 1628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (use->IsPhi()) { 1629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = HPhi::cast(use); 1630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddIndirectUsesTo(&use_count[0]); 1631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch use_count[req_rep.kind()]++; 1633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int tagged_count = use_count[Representation::kTagged]; 1635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int double_count = use_count[Representation::kDouble]; 1636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int int32_count = use_count[Representation::kInteger32]; 1637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int non_tagged_count = double_count + int32_count; 1638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If a non-loop phi has tagged uses, don't convert it to untagged. 1640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->IsPhi() && !current->block()->IsLoopHeader()) { 1641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (tagged_count > 0) return Representation::None(); 1642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (non_tagged_count >= tagged_count) { 1645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // More untagged than tagged. 1646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (double_count > 0) { 1647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is at least one usage that is a double => guess that the 1648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // correct representation is double. 1649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::Double(); 1650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (int32_count > 0) { 1651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::Integer32(); 1652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::None(); 1655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HInferRepresentation::Analyze() { 1659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Infer representations", graph_); 1660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // (1) Initialize bit vectors and count real uses. Each phi 1662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // gets a bit-vector of length <number of phis>. 1663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HPhi*>* phi_list = graph_->phi_list(); 1664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int num_phis = phi_list->length(); 1665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ScopedVector<BitVector*> connected_phis(num_phis); 1666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < num_phis; i++) { 1667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi_list->at(i)->InitRealUses(i); 1668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch connected_phis[i] = new BitVector(num_phis); 1669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch connected_phis[i]->Add(i); 1670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // (2) Do a fixed point iteration to find the set of connected phis. 1673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // A phi is connected to another phi if its value is used either 1674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // directly or indirectly through a transitive closure of the def-use 1675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // relation. 1676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool change = true; 1677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (change) { 1678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch change = false; 1679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < num_phis; i++) { 1680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list->at(i); 1681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < phi->uses()->length(); j++) { 1682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = phi->uses()->at(j); 1683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (use->IsPhi()) { 1684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int phi_use = HPhi::cast(use)->phi_id(); 1685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (connected_phis[i]->UnionIsChanged(*connected_phis[phi_use])) { 1686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch change = true; 1687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // (3) Sum up the non-phi use counts of all connected phis. 1694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Don't include the non-phi uses of the phi itself. 1695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < num_phis; i++) { 1696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list->at(i); 1697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (BitVector::Iterator it(connected_phis.at(i)); 1698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !it.Done(); 1699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch it.Advance()) { 1700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = it.Current(); 1701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (index != i) { 1702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* it_use = phi_list->at(it.Current()); 1703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddNonPhiUsesFrom(it_use); 1704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < graph_->blocks()->length(); ++i) { 1709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph_->blocks()->at(i); 1710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HPhi*>* phis = block->phis(); 1711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < phis->length(); ++j) { 1712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToWorklist(phis->at(j)); 1713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = block->first(); 1716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 1717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToWorklist(current); 1718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 1719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (!worklist_.is_empty()) { 1723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* current = worklist_.RemoveLast(); 1724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch in_worklist_.Remove(current->id()); 1725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferBasedOnInputs(current); 1726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferBasedOnUses(current); 1727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes() { 1732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Inferring types", this); 1733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InitializeInferredTypes(0, this->blocks_.length() - 1); 1734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InitializeInferredTypes(int from_inclusive, int to_inclusive) { 1738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = from_inclusive; i <= to_inclusive; ++i) { 1739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = blocks_[i]; 1740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HPhi*>* phis = block->phis(); 1742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < phis->length(); j++) { 1743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phis->at(j)->UpdateInferredType(); 1744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = block->first(); 1747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 1748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->UpdateInferredType(); 1749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 1750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (block->IsLoopHeader()) { 1753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* last_back_edge = 1754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->loop_information()->GetLastBackEdge(); 1755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InitializeInferredTypes(i + 1, last_back_edge->block_id()); 1756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Skip all blocks already processed by the recursive call. 1757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch i = last_back_edge->block_id(); 1758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Update phis of the loop header now after the whole loop body is 1759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // guaranteed to be processed. 1760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> worklist(block->phis()->length()); 1761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < block->phis()->length(); ++j) { 1762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch worklist.Add(block->phis()->at(j)); 1763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InferTypes(&worklist); 1765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::PropagateMinusZeroChecks(HValue* value, BitVector* visited) { 1771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* current = value; 1772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 1773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (visited->Contains(current->id())) return; 1774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For phis, we must propagate the check to all of its inputs. 1776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->IsPhi()) { 1777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch visited->Add(current->id()); 1778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = HPhi::cast(current); 1779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phi->OperandCount(); ++i) { 1780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(phi->OperandAt(i), visited); 1781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For multiplication and division, we must propagate to the left and 1786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the right side. 1787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->IsMul()) { 1788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HMul* mul = HMul::cast(current); 1789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch mul->EnsureAndPropagateNotMinusZero(visited); 1790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(mul->left(), visited); 1791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(mul->right(), visited); 1792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (current->IsDiv()) { 1793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HDiv* div = HDiv::cast(current); 1794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch div->EnsureAndPropagateNotMinusZero(visited); 1795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(div->left(), visited); 1796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(div->right(), visited); 1797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->EnsureAndPropagateNotMinusZero(visited); 1800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChangeForUse(HValue* value, 1805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use, 1806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation to, 1807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_truncating) { 1808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Propagate flags for negative zero checks upwards from conversions 1809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // int32-to-tagged and int32-to-double. 1810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation from = value->representation(); 1811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (from.IsInteger32()) { 1812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(to.IsTagged() || to.IsDouble()); 1813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BitVector visited(GetMaximumValueID()); 1814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PropagateMinusZeroChecks(value, &visited); 1815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Insert the representation change right before its use. For phi-uses we 1818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // insert at the end of the corresponding predecessor. 1819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* insert_block = use->block(); 1820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (use->IsPhi()) { 1821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = 0; 1822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (use->OperandAt(index) != value) ++index; 1823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch insert_block = insert_block->predecessors()->at(index); 1824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* next = (insert_block == use->block()) 1827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? HInstruction::cast(use) 1828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : insert_block->end(); 1829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // For constants we try to make the representation change at compile 1831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // time. When a representation change is not possible without loss of 1832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // information we treat constants like normal instructions and insert the 1833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // change instructions for them. 1834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* new_value = NULL; 1835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value->IsConstant()) { 1836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* constant = HConstant::cast(value); 1837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Try to create a new copy of the constant with the new representation. 1838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_value = is_truncating 1839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? constant->CopyToTruncatedInt32() 1840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : constant->CopyToRepresentation(to); 1841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (new_value == NULL) { 1844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_value = new HChange(value, value->representation(), to); 1845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_value->InsertBefore(next); 1848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->ReplaceFirstAtUse(use, new_value, to); 1849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochint CompareConversionUses(HValue* a, 1853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* b, 1854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation a_rep, 1855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation b_rep) { 1856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (a_rep.kind() > b_rep.kind()) { 1857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Make sure specializations are separated in the result array. 1858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return 1; 1859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Put truncating conversions before non-truncating conversions. 1861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool a_truncate = a->CheckFlag(HValue::kTruncatingToInt32); 1862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool b_truncate = b->CheckFlag(HValue::kTruncatingToInt32); 1863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (a_truncate != b_truncate) { 1864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return a_truncate ? -1 : 1; 1865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Sort by increasing block ID. 1867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return a->block()->block_id() - b->block()->block_id(); 1868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChanges(HValue* current) { 1872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation r = current->representation(); 1873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (r.IsNone()) return; 1874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->uses()->length() == 0) return; 1875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Collect the representation changes in a sorted list. This allows 1877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // us to avoid duplicate changes without searching the list. 1878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HValue*> to_convert(2); 1879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<Representation> to_convert_reps(2); 1880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < current->uses()->length(); ++i) { 1881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = current->uses()->at(i); 1882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The occurrences index means the index within the operand array of "use" 1883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // at which "current" is used. While iterating through the use array we 1884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // also have to iterate over the different occurrence indices. 1885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int occurrence_index = 0; 1886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (use->UsesMultipleTimes(current)) { 1887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch occurrence_index = current->uses()->CountOccurrences(use, 0, i - 1); 1888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_representation) { 1889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Instruction %d is used multiple times at %d; occurrence=%d\n", 1890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->id(), 1891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch use->id(), 1892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch occurrence_index); 1893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int operand_index = use->LookupOperandIndex(occurrence_index, current); 1896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation req = use->RequiredInputRepresentation(operand_index); 1897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (req.IsNone() || req.Equals(r)) continue; 1898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = 0; 1899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (to_convert.length() > index && 1900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CompareConversionUses(to_convert[index], 1901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch use, 1902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch to_convert_reps[index], 1903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch req) < 0) { 1904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ++index; 1905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_representation) { 1907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Inserting a representation change to %s of %d for use at %d\n", 1908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch req.Mnemonic(), 1909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->id(), 1910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch use->id()); 1911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch to_convert.InsertAt(index, use); 1913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch to_convert_reps.InsertAt(index, req); 1914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < to_convert.length(); ++i) { 1917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = to_convert[i]; 1918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation r_to = to_convert_reps[i]; 1919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_truncating = use->CheckFlag(HValue::kTruncatingToInt32); 1920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InsertRepresentationChangeForUse(current, use, r_to, is_truncating); 1921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->uses()->is_empty()) { 1924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current->IsConstant()); 1925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->Delete(); 1926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraph::InsertRepresentationChanges() { 1931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Insert representation changes", this); 1932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Compute truncation flag for phis: Initially assume that all 1935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // int32-phis allow truncation and iteratively remove the ones that 1936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // are used in an operation that does not allow a truncating 1937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // conversion. 1938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(fschneider): Replace this with a worklist-based iteration. 1939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phi_list()->length(); i++) { 1940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list()->at(i); 1941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (phi->representation().IsInteger32()) { 1942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->SetFlag(HValue::kTruncatingToInt32); 1943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool change = true; 1946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (change) { 1947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch change = false; 1948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < phi_list()->length(); i++) { 1949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = phi_list()->at(i); 1950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!phi->CheckFlag(HValue::kTruncatingToInt32)) continue; 1951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < phi->uses()->length(); j++) { 1952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* use = phi->uses()->at(j); 1953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!use->CheckFlag(HValue::kTruncatingToInt32)) { 1954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->ClearFlag(HValue::kTruncatingToInt32); 1955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch change = true; 1956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 1957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks_.length(); ++i) { 1963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Process phi instructions first. 1964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < blocks_[i]->phis()->length(); j++) { 1965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = blocks_[i]->phis()->at(j); 1966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InsertRepresentationChanges(phi); 1967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Process normal instructions. 1970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* current = blocks_[i]->first(); 1971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current != NULL) { 1972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InsertRepresentationChanges(current); 1973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current = current->next(); 1974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 1976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Implementation of utility classes to represent an expression's context in 1980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// the AST. 1981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::AstContext(HGraphBuilder* owner, Expression::Context kind) 1982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : owner_(owner), kind_(kind), outer_(owner->ast_context()) { 1983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner->set_ast_context(this); // Push. 1984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 19859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block original_length_ = owner->environment()->length(); 1986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 1987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochAstContext::~AstContext() { 1991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner_->set_ast_context(outer_); // Pop. 1992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 1993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 1995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochEffectContext::~EffectContext() { 1996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(owner()->HasStackOverflow() || 1997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !owner()->subgraph()->HasExit() || 19989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block owner()->environment()->length() == original_length_); 1999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochValueContext::~ValueContext() { 2003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(owner()->HasStackOverflow() || 2004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !owner()->subgraph()->HasExit() || 20059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block owner()->environment()->length() == original_length_ + 1); 2006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnValue(HValue* value) { 2010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The value is simply ignored. 2011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnValue(HValue* value) { 2015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The value is tracked in the bailout environment, and communicated 2016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // through the environment as the result of the expression. 2017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->Push(value); 2018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnValue(HValue* value) { 2022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildBranch(value); 2023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid EffectContext::ReturnInstruction(HInstruction* instr, int ast_id) { 2027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->AddInstruction(instr); 2028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); 2029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid ValueContext::ReturnInstruction(HInstruction* instr, int ast_id) { 2033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->AddInstruction(instr); 2034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch owner()->Push(instr); 2035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) owner()->AddSimulate(ast_id); 2036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::ReturnInstruction(HInstruction* instr, int ast_id) { 2040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder* builder = owner(); 2041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->AddInstruction(instr); 2042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We expect a simulate after every expression with side effects, though 2043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // this one isn't actually needed (and wouldn't work if it were targeted). 2044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) { 2045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->Push(instr); 2046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->AddSimulate(ast_id); 2047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->Pop(); 2048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildBranch(instr); 2050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid TestContext::BuildBranch(HValue* value) { 2054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We expect the graph to be in edge-split form: there is no edge that 2055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // connects a branch node to a join node. We conservatively ensure that 2056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // property by always adding an empty block on the outgoing edges of this 2057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // branch. 2058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder* builder = owner(); 2059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); 2060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); 2061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBranch* branch = new HBranch(empty_true, empty_false, value); 2062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->CurrentBlock()->Finish(branch); 2063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* const no_return_value = NULL; 2065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* true_target = if_true(); 2066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_target->IsInlineReturnTarget()) { 2067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch empty_true->AddLeaveInlined(no_return_value, true_target); 2068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch empty_true->Goto(true_target); 2070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* false_target = if_false(); 2073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_target->IsInlineReturnTarget()) { 2074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch empty_false->AddLeaveInlined(no_return_value, false_target); 2075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch empty_false->Goto(false_target); 2077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder->subgraph()->set_exit_block(NULL); 2079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// HGraphBuilder infrastructure for bailing out and checking bailouts. 2083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define BAILOUT(reason) \ 2084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { \ 2085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Bailout(reason); \ 2086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; \ 2087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (false) 2088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define CHECK_BAILOUT \ 2091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { \ 2092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return; \ 2093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (false) 2094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define VISIT_FOR_EFFECT(expr) \ 2097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { \ 2098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForEffect(expr); \ 2099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return; \ 2100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (false) 2101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define VISIT_FOR_VALUE(expr) \ 2104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { \ 2105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(expr); \ 2106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return; \ 2107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (false) 2108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define VISIT_FOR_CONTROL(expr, true_block, false_block) \ 2111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { \ 2112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForControl(expr, true_block, false_block); \ 2113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return; \ 2114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (false) 2115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// 'thing' could be an expression, statement, or list of statements. 2118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define ADD_TO_SUBGRAPH(graph, thing) \ 2119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch do { \ 2120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToSubgraph(graph, thing); \ 2121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return; \ 2122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } while (false) 2123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochclass HGraphBuilder::SubgraphScope BASE_EMBEDDED { 2126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch public: 2127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope(HGraphBuilder* builder, HSubgraph* new_subgraph) 2128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : builder_(builder) { 2129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch old_subgraph_ = builder_->current_subgraph_; 2130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph_ = new_subgraph; 2131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder_->current_subgraph_ = subgraph_; 2132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ~SubgraphScope() { 2135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch old_subgraph_->AddBreakContinueInfo(subgraph_); 2136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch builder_->current_subgraph_ = old_subgraph_; 2137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph() const { return subgraph_; } 2140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch private: 2142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder* builder_; 2143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* old_subgraph_; 2144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph_; 2145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 2146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::Bailout(const char* reason) { 2149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_bailout) { 2150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SmartPointer<char> debug_name = graph()->debug_name()->ToCString(); 2151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Bailout in HGraphBuilder: @\"%s\": %s\n", *debug_name, reason); 2152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetStackOverflow(); 2154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForEffect(Expression* expr) { 2158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch EffectContext for_effect(this); 2159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr); 2160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForValue(Expression* expr) { 2164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ValueContext for_value(this); 2165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr); 2166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForControl(Expression* expr, 2170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* true_block, 2171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* false_block) { 2172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestContext for_test(this, true_block, false_block); 2173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr); 2174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHValue* HGraphBuilder::VisitArgument(Expression* expr) { 2178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(expr); 2179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow() || !subgraph()->HasExit()) return NULL; 2180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return environment()->Top(); 2181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArgumentList(ZoneList<Expression*>* arguments) { 2185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < arguments->length(); i++) { 2186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgument(arguments->at(i)); 2187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow() || !current_subgraph_->HasExit()) return; 2188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHGraph* HGraphBuilder::CreateGraph(CompilationInfo* info) { 2193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current_subgraph_ == NULL); 2194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_ = new HGraph(info); 2195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 2197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Block building"); 2198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->Initialize(CreateBasicBlock(graph_->start_environment())); 2199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_ = graph_; 2200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Scope* scope = info->scope(); 2202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SetupScope(scope); 2203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitDeclarations(scope->declarations()); 2204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HStackCheck()); 2206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<Statement*>* stmts = info->function()->body(); 2208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* body = CreateGotoSubgraph(environment()); 2209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToSubgraph(body, stmts); 2210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return NULL; 2211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->Append(body, NULL); 2212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->entry_block()->SetJoinId(info->function()->id()); 2213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (graph_->HasExit()) { 2215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->FinishExit(new HReturn(graph_->GetConstantUndefined())); 2216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->OrderBlocks(); 2220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->AssignDominators(); 2221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->EliminateRedundantPhis(); 2222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!graph_->CollectPhis()) { 2223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Bailout("Phi-use of arguments object"); 2224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return NULL; 2225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInferRepresentation rep(graph_); 2228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch rep.Analyze(); 2229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_use_range) { 2231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HRangeAnalysis rangeAnalysis(graph_); 2232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch rangeAnalysis.Analyze(); 2233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->InitializeInferredTypes(); 2236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->Canonicalize(); 2237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->InsertRepresentationChanges(); 2238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Eliminate redundant stack checks on backwards branches. 2240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HStackCheckEliminator sce(graph_); 2241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch sce.Process(); 2242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Perform common subexpression elimination and loop-invariant code motion. 2244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_use_gvn) { 2245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhase phase("Global value numbering", graph_); 2246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGlobalValueNumberer gvn(graph_); 2247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch gvn.Analyze(); 2248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return graph_; 2251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddToSubgraph(HSubgraph* graph, Statement* stmt) { 2255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, graph); 2256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(stmt); 2257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddToSubgraph(HSubgraph* graph, Expression* expr) { 2261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, graph); 2262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(expr); 2263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddToSubgraph(HSubgraph* graph, 2267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<Statement*>* stmts) { 2268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, graph); 2269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitStatements(stmts); 2270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) { 2274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current_subgraph_->HasExit()); 2275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->exit_block()->AddInstruction(instr); 2276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 2277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddSimulate(int id) { 2281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current_subgraph_->HasExit()); 2282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->exit_block()->AddSimulate(id); 2283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddPhi(HPhi* instr) { 2287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current_subgraph_->HasExit()); 2288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->exit_block()->AddPhi(instr); 2289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::PushAndAdd(HInstruction* instr) { 2293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(instr); 2294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 2295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::PushArgumentsForStubCall(int argument_count) { 2299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const int kMaxStubArguments = 4; 2300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_GE(kMaxStubArguments, argument_count); 2301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push the arguments on the stack. 2302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* arguments[kMaxStubArguments]; 2303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = argument_count - 1; i >= 0; i--) { 2304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch arguments[i] = Pop(); 2305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < argument_count; i++) { 2307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HPushArgument(arguments[i])); 2308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::ProcessCall(HCall* call) { 2313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = call->argument_count() - 1; i >= 0; --i) { 2314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 2315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPushArgument* push = new HPushArgument(value); 2316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->SetArgumentAt(i, push); 2317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < call->argument_count(); ++i) { 2320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(call->PushArgumentAt(i)); 2321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::SetupScope(Scope* scope) { 2326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't yet handle the function name for named function expressions. 2327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (scope->function() != NULL) BAILOUT("named function expression"); 2328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We can't handle heap-allocated locals. 2330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (scope->num_heap_slots() > 0) BAILOUT("heap allocated locals"); 2331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* undefined_constant = 2333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HConstant(Factory::undefined_value(), Representation::Tagged()); 2334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(undefined_constant); 2335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->set_undefined_constant(undefined_constant); 2336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Set the initial values of parameters including "this". "This" has 2338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // parameter index 0. 2339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int count = scope->num_parameters() + 1; 2340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < count; ++i) { 2341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* parameter = AddInstruction(new HParameter(i)); 2342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->Bind(i, parameter); 2343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Set the initial values of stack-allocated locals. 23469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = count; i < environment()->length(); ++i) { 2347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->Bind(i, undefined_constant); 2348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Handle the arguments and arguments shadow variables specially (they do 2351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // not have declarations). 2352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (scope->arguments() != NULL) { 2353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HArgumentsObject* object = new HArgumentsObject; 2354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(object); 2355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph()->SetArgumentsObject(object); 2356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->Bind(scope->arguments(), object); 2357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->Bind(scope->arguments_shadow(), object); 2358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) { 2363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < statements->length(); i++) { 2364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(statements->at(i)); 2365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow() || !current_subgraph_->HasExit()) break; 2366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) { 2371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* b = graph()->CreateBasicBlock(); 2372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch b->SetInitialEnvironment(env); 2373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return b; 2374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSubgraph* HGraphBuilder::CreateInlinedSubgraph(HEnvironment* outer, 2378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> target, 2379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FunctionLiteral* function) { 2380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* undefined = graph()->GetConstantUndefined(); 2381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* inner = 2382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer->CopyForInlining(target, function, true, undefined); 2383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = new HSubgraph(graph()); 2384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->Initialize(CreateBasicBlock(inner)); 2385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return subgraph; 2386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSubgraph* HGraphBuilder::CreateGotoSubgraph(HEnvironment* env) { 2390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = new HSubgraph(graph()); 2391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* new_env = env->CopyWithoutHistory(); 2392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->Initialize(CreateBasicBlock(new_env)); 2393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return subgraph; 2394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSubgraph* HGraphBuilder::CreateEmptySubgraph() { 2398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = new HSubgraph(graph()); 2399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->Initialize(graph()->CreateBasicBlock()); 2400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return subgraph; 2401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSubgraph* HGraphBuilder::CreateBranchSubgraph(HEnvironment* env) { 2405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = new HSubgraph(graph()); 2406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* new_env = env->Copy(); 2407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->Initialize(CreateBasicBlock(new_env)); 2408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return subgraph; 2409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHSubgraph* HGraphBuilder::CreateLoopHeaderSubgraph(HEnvironment* env) { 2413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = new HSubgraph(graph()); 2414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* block = graph()->CreateBasicBlock(); 2415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* new_env = env->CopyAsLoopHeader(block); 2416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->SetInitialEnvironment(new_env); 2417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->Initialize(block); 2418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->entry_block()->AttachLoopInformation(); 2419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return subgraph; 2420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBlock(Block* stmt) { 2424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt->labels() != NULL) { 2425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* block_graph = CreateGotoSubgraph(environment()); 2426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(block_graph, stmt->statements()); 2427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->Append(block_graph, stmt); 2428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitStatements(stmt->statements()); 2430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitExpressionStatement(ExpressionStatement* stmt) { 2435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForEffect(stmt->expression()); 2436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) { 2440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitIfStatement(IfStatement* stmt) { 2444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt->condition()->ToBooleanIsTrue()) { 2445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(stmt->ThenId()); 2446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(stmt->then_statement()); 2447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (stmt->condition()->ToBooleanIsFalse()) { 2448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(stmt->ElseId()); 2449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(stmt->else_statement()); 2450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* then_graph = CreateEmptySubgraph(); 2452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* else_graph = CreateEmptySubgraph(); 2453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_CONTROL(stmt->condition(), 2454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch then_graph->entry_block(), 2455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else_graph->entry_block()); 2456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch then_graph->entry_block()->SetJoinId(stmt->ThenId()); 2458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(then_graph, stmt->then_statement()); 2459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else_graph->entry_block()->SetJoinId(stmt->ElseId()); 2461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(else_graph, stmt->else_statement()); 2462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->AppendJoin(then_graph, else_graph, stmt); 2464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitContinueStatement(ContinueStatement* stmt) { 2469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->FinishBreakContinue(stmt->target(), true); 2470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBreakStatement(BreakStatement* stmt) { 2474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->FinishBreakContinue(stmt->target(), false); 2475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) { 2479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AstContext* context = call_context(); 2480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (context == NULL) { 2481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Not an inlined return, so an actual one. 2482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(stmt->expression()); 2483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* result = environment()->Pop(); 2484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->FinishExit(new HReturn(result)); 2485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return from an inlined function, visit the subexpression in the 2487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // expression context of the call. 2488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (context->IsTest()) { 2489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestContext* test = TestContext::cast(context); 2490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForControl(stmt->expression(), 2491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch test->if_true(), 2492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch test->if_false()); 2493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* return_value = NULL; 2495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (context->IsEffect()) { 2496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_EFFECT(stmt->expression()); 2497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return_value = graph()->GetConstantUndefined(); 2498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(context->IsValue()); 2500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(stmt->expression()); 2501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return_value = environment()->Pop(); 2502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->exit_block()->AddLeaveInlined(return_value, 2504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function_return_); 2505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->set_exit_block(NULL); 2506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitWithEnterStatement(WithEnterStatement* stmt) { 2512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("WithEnterStatement"); 2513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitWithExitStatement(WithExitStatement* stmt) { 2517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("WithExitStatement"); 2518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHCompare* HGraphBuilder::BuildSwitchCompare(HSubgraph* subgraph, 2522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* switch_value, 2523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CaseClause* clause) { 2524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToSubgraph(subgraph, clause->label()); 2525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return NULL; 2526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* clause_value = subgraph->environment()->Pop(); 2527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCompare* compare = new HCompare(switch_value, 2528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch clause_value, 2529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::EQ_STRICT); 2530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch compare->SetInputRepresentation(Representation::Integer32()); 2531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->exit_block()->AddInstruction(compare); 2532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return compare; 2533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) { 2537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(stmt->tag()); 2538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(3168478): simulate added for tag should be enough. 2539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(stmt->EntryId()); 2540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* switch_value = Pop(); 2541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<CaseClause*>* clauses = stmt->cases(); 2543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int num_clauses = clauses->length(); 2544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (num_clauses == 0) return; 2545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (num_clauses > 128) BAILOUT("SwitchStatement: too many clauses"); 2546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int num_smi_clauses = num_clauses; 2548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < num_clauses; i++) { 2549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CaseClause* clause = clauses->at(i); 2550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (clause->is_default()) continue; 2551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch clause->RecordTypeFeedback(oracle()); 2552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!clause->IsSmiCompare()) { 2553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (i == 0) BAILOUT("SwitchStatement: no smi compares"); 2554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We will deoptimize if the first non-smi compare is reached. 2555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch num_smi_clauses = i; 2556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 2557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!clause->label()->IsSmiLiteral()) { 2559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("SwitchStatement: non-literal switch label"); 2560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The single exit block of the whole switch statement. 2564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* single_exit_block = graph_->CreateBasicBlock(); 2565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Build a series of empty subgraphs for the comparisons. 2567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The default clause does not have a comparison subgraph. 2568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HSubgraph*> compare_graphs(num_smi_clauses); 2569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < num_smi_clauses; i++) { 2570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (clauses->at(i)->is_default()) { 2571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch compare_graphs.Add(NULL); 2572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch compare_graphs.Add(CreateEmptySubgraph()); 2574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* prev_graph = current_subgraph_; 2578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCompare* prev_compare_inst = NULL; 2579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < num_smi_clauses; i++) { 2580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CaseClause* clause = clauses->at(i); 2581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (clause->is_default()) continue; 2582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Finish the previous graph by connecting it to the current. 2584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = compare_graphs.at(i); 2585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prev_compare_inst == NULL) { 2586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(prev_graph == current_subgraph_); 2587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prev_graph->exit_block()->Finish(new HGoto(subgraph->entry_block())); 2588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty = graph()->CreateBasicBlock(); 2590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prev_graph->exit_block()->Finish(new HBranch(empty, 2591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->entry_block(), 2592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prev_compare_inst)); 2593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Build instructions for current subgraph. 2596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(clause->IsSmiCompare()); 2597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prev_compare_inst = BuildSwitchCompare(subgraph, switch_value, clause); 2598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return; 2599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prev_graph = subgraph; 2601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Finish last comparison if there was at least one comparison. 2604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // last_false_block is the (empty) false-block of the last comparison. If 2605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // there are no comparisons at all (a single default clause), it is just 2606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the last block of the current subgraph. 2607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* last_false_block = current_subgraph_->exit_block(); 2608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prev_graph != current_subgraph_) { 2609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_false_block = graph()->CreateBasicBlock(); 2610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty = graph()->CreateBasicBlock(); 2611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prev_graph->exit_block()->Finish(new HBranch(empty, 2612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_false_block, 2613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prev_compare_inst)); 2614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If we have a non-smi compare clause, we deoptimize after trying 2617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // all the previous compares. 2618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (num_smi_clauses < num_clauses) { 2619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_false_block->Finish(new HDeoptimize); 2620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Build statement blocks, connect them to their comparison block and 2623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // to the previous statement block, if there is a fall-through. 2624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* previous_subgraph = NULL; 2625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < num_clauses; i++) { 2626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CaseClause* clause = clauses->at(i); 2627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Subgraph for the statements of the clause is only created when 2628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // it's reachable either from the corresponding compare or as a 2629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // fall-through from previous statements. 2630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = NULL; 2631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (i < num_smi_clauses) { 2633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (clause->is_default()) { 2634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!last_false_block->IsFinished()) { 2635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Default clause: Connect it to the last false block. 2636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph = CreateEmptySubgraph(); 2637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_false_block->Finish(new HGoto(subgraph->entry_block())); 2638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(clause->IsSmiCompare()); 2641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Connect with the corresponding comparison. 2642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph = CreateEmptySubgraph(); 2643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty = 2644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch compare_graphs.at(i)->exit_block()->end()->FirstSuccessor(); 2645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch empty->Finish(new HGoto(subgraph->entry_block())); 2646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for fall-through from previous statement block. 2650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (previous_subgraph != NULL && previous_subgraph->HasExit()) { 2651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (subgraph == NULL) subgraph = CreateEmptySubgraph(); 2652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch previous_subgraph->exit_block()-> 2653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Finish(new HGoto(subgraph->entry_block())); 2654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (subgraph != NULL) { 2657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(subgraph, clause->statements()); 2658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* break_block = subgraph->BundleBreak(stmt); 2659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (break_block != NULL) { 2660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break_block->Finish(new HGoto(single_exit_block)); 2661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch previous_subgraph = subgraph; 2665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the last statement block has a fall-through, connect it to the 2668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // single exit block. 2669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (previous_subgraph != NULL && previous_subgraph->HasExit()) { 2670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch previous_subgraph->exit_block()->Finish(new HGoto(single_exit_block)); 2671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If there is no default clause finish the last comparison's false target. 2674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!last_false_block->IsFinished()) { 2675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch last_false_block->Finish(new HGoto(single_exit_block)); 2676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (single_exit_block->HasPredecessor()) { 2679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->set_exit_block(single_exit_block); 2680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->set_exit_block(NULL); 2682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraph::HasOsrEntryAt(IterationStatement* statement) { 2686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return statement->OsrEntryId() == info()->osr_ast_id(); 2687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HSubgraph::PreProcessOsrEntry(IterationStatement* statement) { 2691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!graph()->HasOsrEntryAt(statement)) return; 2692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* non_osr_entry = graph()->CreateBasicBlock(); 2694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* osr_entry = graph()->CreateBasicBlock(); 2695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* true_value = graph()->GetConstantTrue(); 2696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBranch* branch = new HBranch(non_osr_entry, osr_entry, true_value); 2697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_block()->Finish(branch); 2698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* loop_predecessor = graph()->CreateBasicBlock(); 2700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch non_osr_entry->Goto(loop_predecessor); 2701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int osr_entry_id = statement->OsrEntryId(); 2703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We want the correct environment at the OsrEntry instruction. Build 2704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // it explicitly. The expression stack should be empty. 27059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int count = osr_entry->last_environment()->length(); 2706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(count == (osr_entry->last_environment()->parameter_count() + 2707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch osr_entry->last_environment()->local_count())); 2708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < count; ++i) { 2709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HUnknownOSRValue* unknown = new HUnknownOSRValue; 2710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch osr_entry->AddInstruction(unknown); 2711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch osr_entry->last_environment()->Bind(i, unknown); 2712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch osr_entry->AddSimulate(osr_entry_id); 2715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch osr_entry->AddInstruction(new HOsrEntry(osr_entry_id)); 2716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch osr_entry->Goto(loop_predecessor); 2717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_predecessor->SetJoinId(statement->EntryId()); 2718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch set_exit_block(loop_predecessor); 2719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) { 2723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(subgraph()->HasExit()); 2724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->PreProcessOsrEntry(stmt); 2725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* body_graph = CreateLoopHeaderSubgraph(environment()); 2727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph->ResolveContinue(stmt); 2729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!body_graph->HasExit() || stmt->cond()->ToBooleanIsTrue()) { 2731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->AppendEndless(body_graph, stmt); 2732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* go_back = CreateEmptySubgraph(); 2734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* exit = CreateEmptySubgraph(); 2735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 2736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, body_graph); 2737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_CONTROL(stmt->cond(), 2738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch go_back->entry_block(), 2739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit->entry_block()); 2740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch go_back->entry_block()->SetJoinId(stmt->BackEdgeId()); 2741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit->entry_block()->SetJoinId(stmt->ExitId()); 2742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->AppendDoWhile(body_graph, stmt, go_back, exit); 2744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::ShouldPeel(HSubgraph* cond, HSubgraph* body) { 2749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return FLAG_use_peeling; 2750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitWhileStatement(WhileStatement* stmt) { 2754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(subgraph()->HasExit()); 2755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->PreProcessOsrEntry(stmt); 2756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* cond_graph = NULL; 2758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* body_graph = NULL; 2759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* exit_graph = NULL; 2760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the condition is constant true, do not generate a condition subgraph. 2762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt->cond()->ToBooleanIsTrue()) { 2763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph = CreateLoopHeaderSubgraph(environment()); 2764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cond_graph = CreateLoopHeaderSubgraph(environment()); 2767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph = CreateEmptySubgraph(); 2768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_graph = CreateEmptySubgraph(); 2769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 2770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, cond_graph); 2771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_CONTROL(stmt->cond(), 2772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph->entry_block(), 2773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_graph->entry_block()); 2774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph->entry_block()->SetJoinId(stmt->BodyId()); 2775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_graph->entry_block()->SetJoinId(stmt->ExitId()); 2776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph->ResolveContinue(stmt); 2781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (cond_graph != NULL) { 2783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); 2784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(fschneider): Implement peeling for endless loops as well. 2786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->AppendEndless(body_graph, stmt); 2787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AppendPeeledWhile(IterationStatement* stmt, 2792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* cond_graph, 2793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* body_graph, 2794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* exit_graph) { 2795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* loop = NULL; 2796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (body_graph->HasExit() && stmt != peeled_statement_ && 2797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ShouldPeel(cond_graph, body_graph)) { 2798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Save the last peeled iteration statement to prevent infinite recursion. 2799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch IterationStatement* outer_peeled_statement = peeled_statement_; 2800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch peeled_statement_ = stmt; 2801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop = CreateGotoSubgraph(body_graph->environment()); 2802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(loop, stmt); 2803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch peeled_statement_ = outer_peeled_statement; 2804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->AppendWhile(cond_graph, body_graph, stmt, loop, 2806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_graph); 2807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForStatement(ForStatement* stmt) { 2811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Only visit the init statement in the peeled part of the loop. 2812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt->init() != NULL && peeled_statement_ != stmt) { 2813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(stmt->init()); 2814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 2815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(subgraph()->HasExit()); 2817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->PreProcessOsrEntry(stmt); 2818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* cond_graph = NULL; 2820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* body_graph = NULL; 2821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* exit_graph = NULL; 2822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt->cond() != NULL) { 2823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cond_graph = CreateLoopHeaderSubgraph(environment()); 2824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph = CreateEmptySubgraph(); 2825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_graph = CreateEmptySubgraph(); 2826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 2827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, cond_graph); 2828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_CONTROL(stmt->cond(), 2829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph->entry_block(), 2830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_graph->entry_block()); 2831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph->entry_block()->SetJoinId(stmt->BodyId()); 2832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch exit_graph->entry_block()->SetJoinId(stmt->ExitId()); 2833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph = CreateLoopHeaderSubgraph(environment()); 2836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(body_graph, stmt->body()); 2838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* next_graph = NULL; 2840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph->ResolveContinue(stmt); 2841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (stmt->next() != NULL && body_graph->HasExit()) { 2843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next_graph = CreateGotoSubgraph(body_graph->environment()); 2844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(next_graph, stmt->next()); 2845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body_graph->Append(next_graph, NULL); 2846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch next_graph->entry_block()->SetJoinId(stmt->ContinueId()); 2847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (cond_graph != NULL) { 2850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendPeeledWhile(stmt, cond_graph, body_graph, exit_graph); 2851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->AppendEndless(body_graph, stmt); 2853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitForInStatement(ForInStatement* stmt) { 2858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("ForInStatement"); 2859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) { 2863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("TryCatchStatement"); 2864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitTryFinallyStatement(TryFinallyStatement* stmt) { 2868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("TryFinallyStatement"); 2869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) { 2873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("DebuggerStatement"); 2874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) { 2878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<SharedFunctionInfo> shared_info = 2879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Compiler::BuildFunctionInfo(expr, graph_->info()->script()); 2880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 2881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HFunctionLiteral* instr = 2882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HFunctionLiteral(shared_info, expr->pretenure()); 2883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 2884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitSharedFunctionInfoLiteral( 2888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SharedFunctionInfoLiteral* expr) { 2889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("SharedFunctionInfoLiteral"); 2890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitConditional(Conditional* expr) { 2894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* then_graph = CreateEmptySubgraph(); 2895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* else_graph = CreateEmptySubgraph(); 2896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_CONTROL(expr->condition(), 2897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch then_graph->entry_block(), 2898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else_graph->entry_block()); 2899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch then_graph->entry_block()->SetJoinId(expr->ThenId()); 2901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(then_graph, expr->then_expression()); 2902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else_graph->entry_block()->SetJoinId(expr->ElseId()); 2904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(else_graph, expr->else_expression()); 2905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->AppendJoin(then_graph, else_graph, expr); 2907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 2908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::LookupGlobalPropertyCell(Variable* var, 2912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup, 2913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_store) { 2914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var->is_this()) { 2915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("global this reference"); 2916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!graph()->info()->has_global_object()) { 2918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("no global object to optimize VariableProxy"); 2919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<GlobalObject> global(graph()->info()->global_object()); 2921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch global->Lookup(*var->name(), lookup); 2922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!lookup->IsProperty()) { 2923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("global variable cell not yet introduced"); 2924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup->type() != NORMAL) { 2926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("global variable has accessors"); 2927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_store && lookup->IsReadOnly()) { 2929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("read-only global variable"); 2930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitVariableProxy(VariableProxy* expr) { 2935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* variable = expr->AsVariable(); 2936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (variable == NULL) { 2937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("reference to rewritten variable"); 2938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (variable->IsStackAllocated()) { 2939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (environment()->Lookup(variable)->CheckFlag(HValue::kIsArguments)) { 2940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("unsupported context for arguments object"); 2941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(environment()->Lookup(variable)); 2943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (variable->is_global()) { 2944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 2945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupGlobalPropertyCell(variable, &lookup, false); 2946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 2947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<GlobalObject> global(graph()->info()->global_object()); 2949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(3039103): Handle global property load through an IC call when access 2950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // checks are enabled. 2951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (global->IsAccessCheckNeeded()) { 2952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("global object requires access check"); 2953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 2955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool check_hole = !lookup.IsDontDelete() || lookup.IsReadOnly(); 2956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HLoadGlobal* instr = new HLoadGlobal(cell, check_hole); 2957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 2958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 2959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("reference to non-stack-allocated/non-global variable"); 2960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitLiteral(Literal* expr) { 2965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* instr = new HConstant(expr->handle(), Representation::Tagged()); 2966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 2967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { 2971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HRegExpLiteral* instr = new HRegExpLiteral(expr->pattern(), 2972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->flags(), 2973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->literal_index()); 2974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 2975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) { 2979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HObjectLiteral* literal = (new HObjectLiteral(expr->constant_properties(), 2980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->fast_elements(), 2981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->literal_index(), 2982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->depth())); 2983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The object is expected in the bailout environment during computation 2984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the property values and is the value of the entire expression. 2985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(literal); 2986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->CalculateEmitStore(); 2988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < expr->properties()->length(); i++) { 2990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ObjectLiteral::Property* property = expr->properties()->at(i); 2991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (property->IsCompileTimeValue()) continue; 2992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* key = property->key(); 2994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* value = property->value(); 2995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (property->kind()) { 2997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::MATERIALIZED_LITERAL: 2998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!CompileTimeValue::IsCompileTimeValue(value)); 2999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Fall through. 3000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::COMPUTED: 3001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (key->handle()->IsSymbol()) { 3002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (property->emit_store()) { 3003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(value); 3004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 3005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = Handle<String>::cast(key->handle()); 3006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HStoreNamedGeneric(literal, name, value)); 3007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(key->id()); 3008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_EFFECT(value); 3010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 3012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Fall through. 3014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::PROTOTYPE: 3015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::SETTER: 3016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case ObjectLiteral::Property::GETTER: 3017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("Object literal with complex property"); 3018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: UNREACHABLE(); 3019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) { 3026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<Expression*>* subexprs = expr->values(); 3027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = subexprs->length(); 3028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HArrayLiteral* literal = new HArrayLiteral(expr->constant_elements(), 3030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch length, 3031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->literal_index(), 3032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->depth()); 3033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The array is expected in the bailout environment during computation 3034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the property values and is the value of the entire expression. 3035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(literal); 3036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HLoadElements* elements = NULL; 3038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; i++) { 3040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* subexpr = subexprs->at(i); 3041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If the subexpression is a literal or a simple materialized literal it 3042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // is already set in the cloned array. 3043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue; 3044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(subexpr); 3046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 3047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!Smi::IsValid(i)) BAILOUT("Non-smi key in array literal"); 3048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Load the elements array before the first store. 3050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (elements == NULL) { 3051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch elements = new HLoadElements(literal); 3052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(elements); 3053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = AddInstruction(new HConstant(Handle<Object>(Smi::FromInt(i)), 3056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation::Integer32())); 3057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HStoreKeyedFastElement(elements, key, value)); 3058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(expr->GetIdForElement(i)); 3059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCatchExtensionObject(CatchExtensionObject* expr) { 3065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("CatchExtensionObject"); 3066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHBasicBlock* HGraphBuilder::BuildTypeSwitch(ZoneMapList* maps, 3070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HSubgraph*>* subgraphs, 3071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver, 3072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int join_id) { 3073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(subgraphs->length() == (maps->length() + 1)); 3074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Build map compare subgraphs for all but the first map. 3076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HSubgraph*> map_compare_subgraphs(maps->length() - 1); 3077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = maps->length() - 1; i > 0; --i) { 3078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, subgraph); 3080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* else_subgraph = 3081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (i == (maps->length() - 1)) 3082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? subgraphs->last() 3083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : map_compare_subgraphs.last(); 3084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->exit_block()->Finish( 3085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HCompareMapAndBranch(receiver, 3086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch maps->at(i), 3087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraphs->at(i)->entry_block(), 3088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else_subgraph->entry_block())); 3089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map_compare_subgraphs.Add(subgraph); 3090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Generate first map check to end the current block. 3093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckNonSmi(receiver)); 3094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* else_subgraph = 3095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (maps->length() == 1) ? subgraphs->at(1) : map_compare_subgraphs.last(); 3096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->exit_block()->Finish( 3097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HCompareMapAndBranch(receiver, 3098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map>(maps->first()), 3099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraphs->first()->entry_block(), 3100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch else_subgraph->entry_block())); 3101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Join all the call subgraphs in a new basic block and make 3103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // this basic block the current basic block. 3104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* join_block = graph_->CreateBasicBlock(); 3105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < subgraphs->length(); ++i) { 31069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block HSubgraph* subgraph = subgraphs->at(i); 31079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (subgraph->HasExit()) { 31089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // In an effect context the value of the type switch is not needed. 31099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // There is no need to merge it at the join block only to discard it. 31109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block HBasicBlock* subgraph_exit = subgraph->exit_block(); 31119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (ast_context()->IsEffect()) { 31129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block subgraph_exit->last_environment()->Drop(1); 31139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 31149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block subgraph_exit->Goto(join_block); 3115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (join_block->predecessors()->is_empty()) return NULL; 3119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch join_block->SetJoinId(join_id); 3120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return join_block; 3121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Sets the lookup result and returns true if the store can be inlined. 3125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool ComputeStoredField(Handle<Map> type, 3126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup) { 3128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch type->LookupInDescriptors(NULL, *name, lookup); 3129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!lookup->IsPropertyOrTransition()) return false; 3130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup->type() == FIELD) return true; 3131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return (lookup->type() == MAP_TRANSITION) && 3132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (type->unused_property_fields() > 0); 3133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic int ComputeStoredFieldIndex(Handle<Map> type, 3137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup) { 3139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(lookup->type() == FIELD || lookup->type() == MAP_TRANSITION); 3140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup->type() == FIELD) { 3141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return lookup->GetLocalFieldIndexFromMap(*type); 3142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Map* transition = lookup->GetTransitionMapFromMap(*type); 3144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return transition->PropertyIndexFor(*name) - type->inobject_properties(); 3145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedField(HValue* object, 3150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 3152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> type, 3153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup, 3154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool smi_and_map_check) { 3155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (smi_and_map_check) { 3156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckNonSmi(object)); 3157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckMap(object, type)); 3158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = ComputeStoredFieldIndex(type, name, lookup); 3161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_in_object = index < 0; 3162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = index * kPointerSize; 3163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (index < 0) { 3164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Negative property indices are in-object properties, indexed 3165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // from the end of the fixed part of the object. 3166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch offset += type->instance_size(); 3167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch offset += FixedArray::kHeaderSize; 3169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HStoreNamedField* instr = 3171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HStoreNamedField(object, name, value, is_in_object, offset); 3172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup->type() == MAP_TRANSITION) { 3173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> transition(lookup->GetTransitionMapFromMap(*type)); 3174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_transition(transition); 3175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(fschneider): Record the new map type of the object in the IR to 3176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // enable elimination of redundant checks after the transition store. 3177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->SetFlag(HValue::kChangesMaps); 3178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 3180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamedGeneric(HValue* object, 3184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name, 3185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value) { 3186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new HStoreNamedGeneric(object, name, value); 3187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreNamed(HValue* object, 3191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 3192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* expr) { 3193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = (expr->AsProperty() != NULL) 3194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? expr->AsProperty() 3195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : expr->AsAssignment()->target()->AsProperty(); 3196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* key = prop->key()->AsLiteral(); 3197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = Handle<String>::cast(key->handle()); 3198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!name.is_null()); 3199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 3201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types = expr->GetReceiverTypes(); 3202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_monomorphic = expr->IsMonomorphic() && 3203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ComputeStoredField(types->first(), name, &lookup); 3204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return is_monomorphic 3206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? BuildStoreNamedField(object, name, value, types->first(), &lookup, 3207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true) // Needs smi and map check. 3208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : BuildStoreNamedGeneric(object, name, value); 3209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicStoreNamedField(Assignment* expr, 3213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* object, 3214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 3215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types, 3216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name) { 3217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int number_of_types = Min(types->length(), kMaxStorePolymorphism); 3218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList maps(number_of_types); 3219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HSubgraph*> subgraphs(number_of_types + 1); 3220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool needs_generic = (types->length() > kMaxStorePolymorphism); 3221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Build subgraphs for each of the specific maps. 3223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // 3224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(ager): We should recognize when the prototype chains for 3225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // different maps are identical. In that case we can avoid 3226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // repeatedly generating the same prototype map checks. 3227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < number_of_types; ++i) { 3228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = types->at(i); 3229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 3230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (ComputeStoredField(map, name, &lookup)) { 3231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch maps.Add(map); 3232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, subgraph); 3234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = 3235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildStoreNamedField(object, name, value, map, &lookup, false); 3236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(value); 3237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 3239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraphs.Add(subgraph); 3240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch needs_generic = true; 3242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If none of the properties were named fields we generate a 3246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // generic store. 3247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (maps.length() == 0) { 3248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = new HStoreNamedGeneric(object, name, value); 3249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(value); 3250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 32529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 32539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ast_context()->ReturnValue(Pop()); 3254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Build subgraph for generic store through IC. 3256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 3257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, subgraph); 3259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->FinishExit(new HDeoptimize()); 3261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = new HStoreNamedGeneric(object, name, value); 3263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(value); 3264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 3266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraphs.Add(subgraph); 3268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* new_exit_block = 32719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); 3272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->set_exit_block(new_exit_block); 32739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // In an effect context, we did not materialized the value in the 32749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // predecessor environments so there's no need to handle it here. 32759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (subgraph()->HasExit() && !ast_context()->IsEffect()) { 32769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ast_context()->ReturnValue(Pop()); 32779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 3278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePropertyAssignment(Assignment* expr) { 3283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = expr->target()->AsProperty(); 3284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(prop != NULL); 3285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->RecordTypeFeedback(oracle()); 3286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->obj()); 3287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = NULL; 3289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 3290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->key()->IsPropertyName()) { 3292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named store. 3293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->value()); 3294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = Pop(); 3295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* object = Pop(); 3296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* key = prop->key()->AsLiteral(); 3298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = Handle<String>::cast(key->handle()); 3299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!name.is_null()); 3300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types = expr->GetReceiverTypes(); 3302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 3303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->IsMonomorphic()) { 3305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = BuildStoreNamed(object, value, expr); 3306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (types != NULL && types->length() > 1) { 3308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandlePolymorphicStoreNamedField(expr, object, value, types, name); 3309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 3310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HStoreNamedGeneric(object, name, value); 3313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed store. 3317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->key()); 3318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->value()); 3319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value = Pop(); 3320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 3321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* object = Pop(); 3322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_fast_elements = expr->IsMonomorphic() && 3324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->GetMonomorphicReceiverType()->has_fast_elements(); 3325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = is_fast_elements 3327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? BuildStoreKeyedFastElement(object, key, value, expr) 3328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : BuildStoreKeyedGeneric(object, key, value); 3329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(value); 3332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 3334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Because not every expression has a position and there is not common 3340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// superclass of Assignment and CountOperation, we cannot just pass the 3341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// owning expression instead of position and ast_id separately. 3342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleGlobalVariableAssignment(Variable* var, 3343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value, 3344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int position, 3345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 3346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 3347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupGlobalPropertyCell(var, &lookup, true); 3348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 3349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<GlobalObject> global(graph()->info()->global_object()); 3351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(&lookup)); 3352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = new HStoreGlobal(value, cell); 3353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(position); 3354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(instr); 3355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) AddSimulate(ast_id); 3356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandleCompoundAssignment(Assignment* expr) { 3360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* target = expr->target(); 3361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = target->AsVariableProxy(); 3362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = proxy->AsVariable(); 3363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = target->AsProperty(); 3364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(var == NULL || prop == NULL); 3365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We have a second position recorded in the FullCodeGenerator to have 3367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // type feedback for the binary operation. 3368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BinaryOperation* operation = expr->binary_operation(); 3369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch operation->RecordTypeFeedback(oracle()); 3370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var != NULL) { 3372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!var->is_global() && !var->IsStackAllocated()) { 3373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("non-stack/non-global in compound assignment"); 3374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(operation); 3377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var->is_global()) { 3379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleGlobalVariableAssignment(var, 3380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Top(), 3381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->position(), 3382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->AssignmentId()); 3383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Bind(var, Top()); 3385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (prop != NULL) { 3389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prop->RecordTypeFeedback(oracle()); 3390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->key()->IsPropertyName()) { 3392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named property. 3393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->obj()); 3394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Top(); 3395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* load = NULL; 3397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->IsMonomorphic()) { 3398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 3399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = prop->GetReceiverTypes()->first(); 3400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamed(obj, prop, map, name); 3401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamedGeneric(obj, prop); 3403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 3405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); 3406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->value()); 3408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 3409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 3410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = BuildBinaryOperation(operation, left, right); 3412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(instr); 3413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) AddSimulate(operation->id()); 3414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* store = BuildStoreNamed(obj, instr, prop); 3416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 3417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop the simulated receiver and value. Return the value. 3418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(2); 3419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(instr); 3420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed property. 3425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->obj()); 3426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->key()); 3427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = environment()->ExpressionStackAt(1); 3428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = environment()->ExpressionStackAt(0); 3429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_fast_elements = prop->IsMonomorphic() && 3431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prop->GetMonomorphicReceiverType()->has_fast_elements(); 3432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* load = is_fast_elements 3434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? BuildLoadKeyedFastElement(obj, key, prop) 3435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : BuildLoadKeyedGeneric(obj, key); 3436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 3437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (load->HasSideEffects()) AddSimulate(expr->CompoundLoadId()); 3438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->value()); 3440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 3441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 3442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = BuildBinaryOperation(operation, left, right); 3444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(instr); 3445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (instr->HasSideEffects()) AddSimulate(operation->id()); 3446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* store = is_fast_elements 3448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? BuildStoreKeyedFastElement(obj, key, instr, prop) 3449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : BuildStoreKeyedGeneric(obj, key, instr); 3450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 3451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop the simulated receiver, key, and value. Return the value. 3452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(3); 3453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(instr); 3454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 3455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("invalid lhs in compound assignment"); 3460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitAssignment(Assignment* expr) { 3465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = expr->target()->AsVariableProxy(); 3466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = proxy->AsVariable(); 3467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = expr->target()->AsProperty(); 3468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(var == NULL || prop == NULL); 3469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->is_compound()) { 3471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleCompoundAssignment(expr); 3472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 3473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var != NULL) { 3476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (proxy->IsArguments()) BAILOUT("assignment to arguments"); 3477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Handle the assignment. 3479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var->is_global()) { 3480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->value()); 3481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleGlobalVariableAssignment(var, 3482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Top(), 3483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->position(), 3484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->AssignmentId()); 3485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We allow reference to the arguments object only in assignemtns 3487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // to local variables to make sure that the arguments object does 3488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // not escape and is not modified. 3489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* rhs = expr->value()->AsVariableProxy(); 3490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (rhs != NULL && 3491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch rhs->var()->IsStackAllocated() && 3492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->Lookup(rhs->var())->CheckFlag(HValue::kIsArguments)) { 3493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(environment()->Lookup(rhs->var())); 3494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->value()); 3496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Bind(proxy->var(), Top()); 3498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return the value. 3500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 3501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (prop != NULL) { 3503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandlePropertyAssignment(expr); 3504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("unsupported invalid lhs"); 3506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThrow(Throw* expr) { 3511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't optimize functions with invalid left-hand sides in 3512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // assignments, count operations, or for-in. Consequently throw can 3513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // currently only occur in an effect context. 3514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ast_context()->IsEffect()); 3515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->exception()); 3516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = environment()->Pop(); 3518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HControlInstruction* instr = new HThrow(value); 3519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->FinishExit(instr); 3521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicLoadNamedField(Property* expr, 3525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* object, 3526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types, 3527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name) { 3528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int number_of_types = Min(types->length(), kMaxLoadPolymorphism); 3529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList maps(number_of_types); 3530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HSubgraph*> subgraphs(number_of_types + 1); 3531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool needs_generic = (types->length() > kMaxLoadPolymorphism); 3532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Build subgraphs for each of the specific maps. 3534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // 3535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(ager): We should recognize when the prototype chains for 3536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // different maps are identical. In that case we can avoid 3537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // repeatedly generating the same prototype map checks. 3538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < number_of_types; ++i) { 3539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = types->at(i); 3540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 3541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->LookupInDescriptors(NULL, *name, &lookup); 3542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup.IsProperty() && lookup.type() == FIELD) { 3543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch maps.Add(map); 3544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, subgraph); 3546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HLoadNamedField* instr = 3547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildLoadNamedField(object, expr, map, &lookup, false); 3548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->ClearFlag(HValue::kUseGVN); // Don't do GVN on polymorphic loads. 3550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(instr); 3551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraphs.Add(subgraph); 3552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch needs_generic = true; 3554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If none of the properties were named fields we generate a 3558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // generic load. 3559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (maps.length() == 0) { 3560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = BuildLoadNamedGeneric(object, expr); 3561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 35629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ast_context()->ReturnInstruction(instr, expr->id()); 3563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Build subgraph for generic load through IC. 3565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 3566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, subgraph); 3568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->FinishExit(new HDeoptimize()); 3570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = BuildLoadNamedGeneric(object, expr); 3572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(instr); 3574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraphs.Add(subgraph); 3576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* new_exit_block = 3579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildTypeSwitch(&maps, &subgraphs, object, expr->id()); 3580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->set_exit_block(new_exit_block); 35819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // In an effect context, we did not materialized the value in the 35829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // predecessor environments so there's no need to handle it here. 35839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (subgraph()->HasExit() && !ast_context()->IsEffect()) { 35849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ast_context()->ReturnValue(Pop()); 35859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 3586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHLoadNamedField* HGraphBuilder::BuildLoadNamedField(HValue* object, 3591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr, 3592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> type, 3593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult* lookup, 3594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool smi_and_map_check) { 3595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (smi_and_map_check) { 3596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckNonSmi(object)); 3597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckMap(object, type)); 3598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int index = lookup->GetLocalFieldIndexFromMap(*type); 3601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (index < 0) { 3602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Negative property indices are in-object properties, indexed 3603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // from the end of the fixed part of the object. 3604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = (index * kPointerSize) + type->instance_size(); 3605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new HLoadNamedField(object, true, offset); 3606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Non-negative property indices are in the properties array. 3608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int offset = (index * kPointerSize) + FixedArray::kHeaderSize; 3609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new HLoadNamedField(object, false, offset); 3610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamedGeneric(HValue* obj, 3615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr) { 3616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(expr->key()->IsPropertyName()); 3617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Object> name = expr->key()->AsLiteral()->handle(); 3618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new HLoadNamedGeneric(obj, name); 3619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadNamed(HValue* obj, 3623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr, 3624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map, 3625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name) { 3626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LookupResult lookup; 3627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map->LookupInDescriptors(NULL, *name, &lookup); 3628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (lookup.IsProperty() && lookup.type() == FIELD) { 3629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return BuildLoadNamedField(obj, 3630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr, 3631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch map, 3632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &lookup, 3633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true); 3634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (lookup.IsProperty() && lookup.type() == CONSTANT_FUNCTION) { 3635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckNonSmi(obj)); 3636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckMap(obj, map)); 3637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> function(lookup.GetConstantFunctionFromMap(*map)); 3638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new HConstant(function, Representation::Tagged()); 3639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return BuildLoadNamedGeneric(obj, expr); 3641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedGeneric(HValue* object, 3646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key) { 3647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new HLoadKeyedGeneric(object, key); 3648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildLoadKeyedFastElement(HValue* object, 3652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key, 3653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* expr) { 3654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!expr->key()->IsPropertyName() && expr->IsMonomorphic()); 3655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckNonSmi(object)); 3656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = expr->GetMonomorphicReceiverType(); 3657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(map->has_fast_elements()); 3658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckMap(object, map)); 36599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block bool is_array = (map->instance_type() == JS_ARRAY_TYPE); 36609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block HLoadElements* elements = new HLoadElements(object); 36619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block HInstruction* length = NULL; 36629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (is_array) { 36639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block length = AddInstruction(new HJSArrayLength(object)); 36649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block AddInstruction(new HBoundsCheck(key, length)); 36659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block AddInstruction(elements); 36669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 36679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block AddInstruction(elements); 36689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block length = AddInstruction(new HFixedArrayLength(elements)); 36699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block AddInstruction(new HBoundsCheck(key, length)); 36709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 3671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new HLoadKeyedFastElement(elements, key); 3672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedGeneric(HValue* object, 3676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key, 3677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value) { 3678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new HStoreKeyedGeneric(object, key, value); 3679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildStoreKeyedFastElement(HValue* object, 3683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key, 3684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* val, 3685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* expr) { 3686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(expr->IsMonomorphic()); 3687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckNonSmi(object)); 3688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = expr->GetMonomorphicReceiverType(); 3689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(map->has_fast_elements()); 3690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckMap(object, map)); 3691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* elements = AddInstruction(new HLoadElements(object)); 3692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckMap(elements, Factory::fixed_array_map())); 3693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_array = (map->instance_type() == JS_ARRAY_TYPE); 3694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* length = NULL; 3695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_array) { 36969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block length = AddInstruction(new HJSArrayLength(object)); 3697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 36989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block length = AddInstruction(new HFixedArrayLength(elements)); 3699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HBoundsCheck(key, length)); 3701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new HStoreKeyedFastElement(elements, key, val); 3702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryArgumentsAccess(Property* expr) { 3706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = expr->obj()->AsVariableProxy(); 3707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (proxy == NULL) return false; 3708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!proxy->var()->IsStackAllocated()) return false; 3709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) { 3710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 3711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* result = NULL; 3714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->key()->IsPropertyName()) { 3715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 3716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!name->IsEqualTo(CStrVector("length"))) return false; 3717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* elements = AddInstruction(new HArgumentsElements); 3718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = new HArgumentsLength(elements); 3719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(expr->key()); 3721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return false; 3722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 3723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* elements = AddInstruction(new HArgumentsElements); 3724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 3725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HBoundsCheck(key, length)); 3726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = new HAccessArgumentsAt(elements, length, key); 3727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 3729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 3730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitProperty(Property* expr) { 3734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->RecordTypeFeedback(oracle()); 3735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (TryArgumentsAccess(expr)) return; 3737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 3738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->obj()); 3740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 3742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->IsArrayLength()) { 3743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* array = Pop(); 3744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckNonSmi(array)); 37459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block AddInstruction(new HCheckInstanceType(array, JS_ARRAY_TYPE, JS_ARRAY_TYPE)); 37469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block instr = new HJSArrayLength(array); 37479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 37489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else if (expr->IsFunctionPrototype()) { 37499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block HValue* function = Pop(); 37509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block AddInstruction(new HCheckNonSmi(function)); 37519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block instr = new HLoadFunctionPrototype(function); 3752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (expr->key()->IsPropertyName()) { 3754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = expr->key()->AsLiteral()->AsPropertyName(); 3755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types = expr->GetReceiverTypes(); 3756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Pop(); 3758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->IsMonomorphic()) { 3759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = BuildLoadNamed(obj, expr, types->first(), name); 3760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (types != NULL && types->length() > 1) { 3761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandlePolymorphicLoadNamedField(expr, obj, types, name); 3762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 3763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = BuildLoadNamedGeneric(obj, expr); 3766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->key()); 3770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 3772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Pop(); 3773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_fast_elements = expr->IsMonomorphic() && 3775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->GetMonomorphicReceiverType()->has_fast_elements(); 3776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = is_fast_elements 3778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? BuildLoadKeyedFastElement(obj, key, expr) 3779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : BuildLoadKeyedGeneric(obj, key); 3780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 3782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 3783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AddCheckConstantFunction(Call* expr, 3787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver, 3788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> receiver_map, 3789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool smi_and_map_check) { 3790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Constant functions have the nice property that the map will change if they 3791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // are overwritten. Therefore it is enough to check the map of the holder and 3792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // its prototypes. 3793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (smi_and_map_check) { 3794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckNonSmi(receiver)); 3795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckMap(receiver, receiver_map)); 3796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!expr->holder().is_null()) { 3798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckPrototypeMaps(receiver, 3799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->holder(), 3800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch receiver_map)); 3801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::HandlePolymorphicCallNamed(Call* expr, 3806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver, 3807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types, 3808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name) { 3809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length() + 1; // Plus receiver. 3810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int number_of_types = Min(types->length(), kMaxCallPolymorphism); 3811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList maps(number_of_types); 3812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<HSubgraph*> subgraphs(number_of_types + 1); 3813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool needs_generic = (types->length() > kMaxCallPolymorphism); 3814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Build subgraphs for each of the specific maps. 3816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // 3817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(ager): We should recognize when the prototype chains for different 3818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // maps are identical. In that case we can avoid repeatedly generating the 3819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // same prototype map checks. 3820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < number_of_types; ++i) { 3821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = types->at(i); 3822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->ComputeTarget(map, name)) { 3823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch maps.Add(map); 3824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, subgraph); 3826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddCheckConstantFunction(expr, receiver, map, false); 3827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_inlining && FLAG_polymorphic_inlining) { 3828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Trying to inline the polymorphic call to %s\n", 3829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch *name->ToCString()); 3830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!FLAG_polymorphic_inlining || !TryInline(expr)) { 3832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for bailout, as trying to inline might fail due to bailout 3833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // during hydrogen processing. 3834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 3835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCall* call = new HCallConstantFunction(expr->target(), argument_count); 3836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 3837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ProcessCall(call); 3838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(call); 3839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraphs.Add(subgraph); 3841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch needs_generic = true; 3843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If we couldn't compute the target for any of the maps just perform an 3847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // IC call. 3848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (maps.length() == 0) { 3849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCall* call = new HCallNamed(name, argument_count); 3850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 3851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ProcessCall(call); 3852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(call, expr->id()); 3853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Build subgraph for generic call through IC. 3855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 3856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* subgraph = CreateBranchSubgraph(environment()); 3857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SubgraphScope scope(this, subgraph); 3858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!needs_generic && FLAG_deoptimize_uncommon_cases) { 3859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph->FinishExit(new HDeoptimize()); 3860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCall* call = new HCallNamed(name, argument_count); 3862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 3863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ProcessCall(call); 3864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(call); 3865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraphs.Add(subgraph); 3867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* new_exit_block = 3870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuildTypeSwitch(&maps, &subgraphs, receiver, expr->id()); 3871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->set_exit_block(new_exit_block); 38729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // In an effect context, we did not materialized the value in the 38739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // predecessor environments so there's no need to handle it here. 38749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (new_exit_block != NULL && !ast_context()->IsEffect()) { 38759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ast_context()->ReturnValue(Pop()); 38769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 3877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::TraceInline(Handle<JSFunction> target, bool result) { 3882b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SmartPointer<char> callee = target->shared()->DebugName()->ToCString(); 3883b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch SmartPointer<char> caller = 3884b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph()->info()->function()->debug_name()->ToCString(); 3885b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (result) { 3886b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Inlined %s called from %s.\n", *callee, *caller); 3887b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 3888b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Do not inline %s called from %s.\n", *callee, *caller); 3889b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3890b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 3891b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3892b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3893b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryInline(Call* expr) { 3894b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!FLAG_use_inlining) return false; 3895b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3896b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Precondition: call is monomorphic and we have found a target with the 3897b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // appropriate arity. 3898b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> target = expr->target(); 3899b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3900b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Do a quick check on source code length to avoid parsing large 3901b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // inlining candidates. 3902b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_limit_inlining && target->shared()->SourceSize() > kMaxSourceSize) { 3903b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_inlining) TraceInline(target, false); 3904b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 3905b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3906b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3907b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Target must be inlineable. 3908b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!target->IsInlineable()) return false; 3909b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3910b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // No context change required. 3911b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CompilationInfo* outer_info = graph()->info(); 3912b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (target->context() != outer_info->closure()->context() || 3913b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_info->scope()->contains_with() || 3914b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_info->scope()->num_heap_slots() > 0) { 3915b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 3916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Don't inline deeper than two calls. 3919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* env = environment(); 3920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (env->outer() != NULL && env->outer()->outer() != NULL) return false; 3921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3922b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Don't inline recursive functions. 3923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (target->shared() == outer_info->closure()->shared()) return false; 3924b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We don't want to add more than a certain number of nodes from inlining. 3926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_limit_inlining && inlined_count_ > kMaxInlinedNodes) { 3927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_inlining) TraceInline(target, false); 3928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 3929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int count_before = AstNode::Count(); 3932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Parse and allocate variables. 3934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<SharedFunctionInfo> shared(target->shared()); 3935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CompilationInfo inner_info(shared); 3936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!ParserApi::Parse(&inner_info) || 3937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !Scope::Analyze(&inner_info)) { 3938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 3939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FunctionLiteral* function = inner_info.function(); 3941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Count the number of AST nodes added by inlining this call. 3943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int nodes_added = AstNode::Count() - count_before; 3944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_limit_inlining && nodes_added > kMaxInlinedSize) { 3945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_inlining) TraceInline(target, false); 3946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 3947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check if we can handle all declarations in the inlined functions. 3950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitDeclarations(inner_info.scope()->declarations()); 3951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) { 3952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ClearStackOverflow(); 3953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 3954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Don't inline functions that uses the arguments object or that 3957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // have a mismatching number of parameters. 3958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity = expr->arguments()->length(); 3959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (function->scope()->arguments() != NULL || 3960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch arity != target->shared()->formal_parameter_count()) { 3961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 3962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // All statements in the body must be inlineable. 3965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0, count = function->body()->length(); i < count; ++i) { 3966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!function->body()->at(i)->IsInlineable()) return false; 3967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Generate the deoptimization data for the unoptimized version of 3970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // the target function if we don't already have it. 3971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!shared->has_deoptimization_support()) { 3972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Note that we compile here using the same AST that we will use for 3973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // generating the optimized inline code. 3974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inner_info.EnableDeoptimizationSupport(); 3975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!FullCodeGenerator::MakeCode(&inner_info)) return false; 3976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch shared->EnableDeoptimizationSupport(*inner_info.code()); 3977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Compiler::RecordFunctionCompilation( 3978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Logger::FUNCTION_TAG, 3979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String>(shared->DebugName()), 3980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch shared->start_position(), 3981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &inner_info); 3982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 3983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Save the pending call context and type feedback oracle. Set up new ones 3985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // for the inlined function. 3986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(shared->has_deoptimization_support()); 3987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AstContext* saved_call_context = call_context(); 3988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* saved_function_return = function_return(); 3989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TypeFeedbackOracle* saved_oracle = oracle(); 3990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // On-stack replacement cannot target inlined functions. Since we don't 3991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // use a separate CompilationInfo structure for the inlined function, we 3992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // save and restore the AST ID in the original compilation info. 3993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int saved_osr_ast_id = graph()->info()->osr_ast_id(); 3994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 3995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestContext* test_context = NULL; 3996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (ast_context()->IsTest()) { 3997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Inlined body is treated as if it occurs in an 'inlined' call context 3998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // with true and false blocks that will forward to the real ones. 3999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* if_true = graph()->CreateBasicBlock(); 4000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* if_false = graph()->CreateBasicBlock(); 4001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if_true->MarkAsInlineReturnTarget(); 4002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if_false->MarkAsInlineReturnTarget(); 4003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // AstContext constructor pushes on the context stack. 4004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch test_context = new TestContext(this, if_true, if_false); 4005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function_return_ = NULL; 4006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Inlined body is treated as if it occurs in the original call context. 4008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function_return_ = graph()->CreateBasicBlock(); 4009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function_return_->MarkAsInlineReturnTarget(); 4010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call_context_ = ast_context(); 4012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TypeFeedbackOracle new_oracle(Handle<Code>(shared->code())); 4013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch oracle_ = &new_oracle; 4014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph()->info()->SetOsrAstId(AstNode::kNoNumber); 4015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* body = CreateInlinedSubgraph(env, target, function); 4017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->exit_block()->AddInstruction(new HEnterInlined(target, function)); 4018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddToSubgraph(body, function->body()); 4019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) { 4020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Bail out if the inline function did, as we cannot residualize a call 4021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // instead. 4022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch delete test_context; 4023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call_context_ = saved_call_context; 4024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function_return_ = saved_function_return; 4025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch oracle_ = saved_oracle; 4026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph()->info()->SetOsrAstId(saved_osr_ast_id); 4027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Update inlined nodes count. 4031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inlined_count_ += nodes_added; 4032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_inlining) TraceInline(target, true); 4034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (body->HasExit()) { 4036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Add a return of undefined if control can fall off the body. In a 4037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // test context, undefined is false. 4038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* return_value = graph()->GetConstantUndefined(); 4039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (test_context == NULL) { 4040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(function_return_ != NULL); 4041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->exit_block()->AddLeaveInlined(return_value, function_return_); 4042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The graph builder assumes control can reach both branches of a 4044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // test, so we materialize the undefined value and test it rather than 4045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // simply jumping to the false target. 4046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // 4047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(3168478): refactor to avoid this. 4048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty_true = graph()->CreateBasicBlock(); 4049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* empty_false = graph()->CreateBasicBlock(); 4050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBranch* branch = 4051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HBranch(empty_true, empty_false, return_value); 4052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->exit_block()->Finish(branch); 4053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* const no_return_value = NULL; 4055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch empty_true->AddLeaveInlined(no_return_value, test_context->if_true()); 4056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch empty_false->AddLeaveInlined(no_return_value, test_context->if_false()); 4057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch body->set_exit_block(NULL); 4059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Record the environment at the inlined function call. 4062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddSimulate(expr->ReturnId()); 4063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Jump to the function entry (without re-recording the environment). 4065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->exit_block()->Finish(new HGoto(body->entry_block())); 4066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Fix up the function exits. 4068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (test_context != NULL) { 4069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* if_true = test_context->if_true(); 4070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* if_false = test_context->if_false(); 4071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if_true->SetJoinId(expr->id()); 4072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if_false->SetJoinId(expr->id()); 4073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(ast_context() == test_context); 4074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch delete test_context; // Destructor pops from expression context stack. 4075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Forward to the real test context. 4077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* const no_return_value = NULL; 4078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* true_target = TestContext::cast(ast_context())->if_true(); 4079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (true_target->IsInlineReturnTarget()) { 4080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if_true->AddLeaveInlined(no_return_value, true_target); 4081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if_true->Goto(true_target); 4083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* false_target = TestContext::cast(ast_context())->if_false(); 4086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (false_target->IsInlineReturnTarget()) { 4087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if_false->AddLeaveInlined(no_return_value, false_target); 4088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if_false->Goto(false_target); 4090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // TODO(kmillikin): Come up with a better way to handle this. It is too 4093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // subtle. NULL here indicates that the enclosing context has no control 4094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // flow to handle. 4095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->set_exit_block(NULL); 4096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function_return_->SetJoinId(expr->id()); 4099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->set_exit_block(function_return_); 4100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call_context_ = saved_call_context; 4103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function_return_ = saved_function_return; 4104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch oracle_ = saved_oracle; 4105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph()->info()->SetOsrAstId(saved_osr_ast_id); 4106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HBasicBlock::AddLeaveInlined(HValue* return_value, HBasicBlock* target) { 4112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(target->IsInlineReturnTarget()); 4113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HLeaveInlined); 4114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* outer = last_environment()->outer(); 4115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (return_value != NULL) outer->Push(return_value); 4116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UpdateEnvironment(outer); 4117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Goto(target); 4118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryMathFunctionInline(Call* expr) { 4122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Try to inline calls like Math.* as operations in the calling function. 4123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!expr->target()->shared()->IsBuiltinMathFunction()) return false; 4124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); 4125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (id) { 4127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathRound: 4128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathFloor: 4129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathAbs: 4130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathSqrt: 4131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathLog: 4132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathSin: 4133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathCos: 4134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (argument_count == 2) { 4135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* argument = Pop(); 4136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(1); // Receiver. 4137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HUnaryMathOperation* op = new HUnaryMathOperation(argument, id); 4138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch op->set_position(expr->position()); 4139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(op, expr->id()); 4140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case kMathPow: 4144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (argument_count == 3) { 4145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 4146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 4147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Pop(); // Pop receiver. 4148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* result = NULL; 4149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Use sqrt() if exponent is 0.5 or -0.5. 4150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) { 4151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double exponent = HConstant::cast(right)->DoubleValue(); 4152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (exponent == 0.5) { 4153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = new HUnaryMathOperation(left, kMathPowHalf); 4154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 4155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (exponent == -0.5) { 4157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* double_one = 4158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HConstant(Handle<Object>(Smi::FromInt(1)), 4159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation::Double()); 4160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(double_one); 4161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HUnaryMathOperation* square_root = 4162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HUnaryMathOperation(left, kMathPowHalf); 4163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(square_root); 4164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // MathPowHalf doesn't have side effects so there's no need for 4165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // an environment simulation here. 4166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!square_root->HasSideEffects()); 4167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = new HDiv(double_one, square_root); 4168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 4169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (exponent == 2.0) { 4171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = new HMul(left, left); 4172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 4173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (right->IsConstant() && 4176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant::cast(right)->HasInteger32Value() && 4177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant::cast(right)->Integer32Value() == 2) { 4178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = new HMul(left, left); 4179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 4180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result = new HPower(left, right); 4184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 4185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 4189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Not yet supported for inlining. 4190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return false; 4193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochbool HGraphBuilder::TryCallApply(Call* expr) { 4197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* callee = expr->expression(); 4198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = callee->AsProperty(); 4199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(prop != NULL); 4200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (graph()->info()->scope()->arguments() == NULL) return false; 4202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!name->IsEqualTo(CStrVector("apply"))) return false; 4205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneList<Expression*>* args = expr->arguments(); 4207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (args->length() != 2) return false; 4208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* arg_two = args->at(1)->AsVariableProxy(); 4210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false; 4211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* arg_two_value = environment()->Lookup(arg_two->var()); 4212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false; 4213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!expr->IsMonomorphic()) return false; 4215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Found pattern f.apply(receiver, arguments). 4217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(prop->obj()); 4218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return false; 4219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* function = Pop(); 4220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForValue(args->at(0)); 4221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (HasStackOverflow()) return false; 4222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver = Pop(); 4223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* elements = AddInstruction(new HArgumentsElements); 4224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 4225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddCheckConstantFunction(expr, 4226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch function, 4227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->GetReceiverTypes()->first(), 4228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true); 4229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* result = 4230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HApplyArguments(function, receiver, length, elements); 4231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_position(expr->position()); 4232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, expr->id()); 4233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCall(Call* expr) { 4238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* callee = expr->expression(); 4239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length() + 1; // Plus receiver. 4240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCall* call = NULL; 4241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = callee->AsProperty(); 4243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop != NULL) { 4244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!prop->key()->IsPropertyName()) { 4245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed function call. 4246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgument(prop->obj()); 4247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->key()); 4250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push receiver and key like the non-optimized code generator expects it. 4251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 4252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver = Pop(); 4253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(key); 4254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(receiver); 4255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgumentList(expr->arguments()); 4257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call = new HCallKeyed(key, argument_count); 4260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 4261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ProcessCall(call); 4262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(1); // Key. 4263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(call, expr->id()); 4264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named function call. 4268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->RecordTypeFeedback(oracle()); 4269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (TryCallApply(expr)) return; 4271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* receiver = VisitArgument(prop->obj()); 4274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgumentList(expr->arguments()); 4276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->RecordTypeFeedback(oracle()); 4281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ZoneMapList* types = expr->GetReceiverTypes(); 4282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->IsMonomorphic()) { 4284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddCheckConstantFunction(expr, receiver, types->first(), true); 4285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (TryMathFunctionInline(expr)) { 4287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (TryInline(expr)) { 4289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (subgraph()->HasExit()) { 4290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* return_value = Pop(); 4291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If we inlined a function in a test context then we need to emit 4292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // a simulate here to shadow the ones at the end of the 4293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // predecessor blocks. Those environments contain the return 4294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // value on top and do not correspond to any actual state of the 4295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // unoptimized code. 4296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (ast_context()->IsEffect()) AddSimulate(expr->id()); 4297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(return_value); 4298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for bailout, as the TryInline call in the if condition above 4302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // might return false due to bailout during hydrogen processing. 4303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call = new HCallConstantFunction(expr->target(), argument_count); 4305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (types != NULL && types->length() > 1) { 4308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandlePolymorphicCallNamed(expr, receiver, types, name); 4309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call = new HCallNamed(name, argument_count); 4313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool global_call = (var != NULL) && var->is_global() && !var->is_this(); 4318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!global_call) { 4320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ++argument_count; 4321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgument(expr->expression()); 4322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (global_call) { 4326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If there is a global property cell for the name at compile time and 4327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // access check is not enabled we assume that the function will not change 4328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // and generate optimized code for calling the function. 4329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CompilationInfo* info = graph()->info(); 4330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool known_global_function = info->has_global_object() && 4331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !info->global_object()->IsAccessCheckNeeded() && 4332b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->ComputeGlobalTarget(Handle<GlobalObject>(info->global_object()), 4333b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch var->name()); 4334b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (known_global_function) { 4335b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Push the global object instead of the global receiver because 4336b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // code generated by the full code generator expects it. 4337b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(new HGlobalObject); 4338b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgumentList(expr->arguments()); 4339b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4340b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4341b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->expression()); 4342b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* function = Pop(); 4343b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(new HCheckFunction(function, expr->target())); 4344b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Replace the global object with the global receiver. 4346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGlobalReceiver* global_receiver = new HGlobalReceiver; 4347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Index of the receiver from the top of the expression stack. 4348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const int receiver_index = argument_count - 1; 4349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(global_receiver); 4350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(environment()->ExpressionStackAt(receiver_index)-> 4351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch IsGlobalObject()); 4352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(receiver_index, global_receiver); 4353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (TryInline(expr)) { 4355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (subgraph()->HasExit()) { 4356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* return_value = Pop(); 4357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If we inlined a function in a test context then we need to 4358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // emit a simulate here to shadow the ones at the end of the 4359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // predecessor blocks. Those environments contain the return 4360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // value on top and do not correspond to any actual state of the 4361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // unoptimized code. 4362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (ast_context()->IsEffect()) AddSimulate(expr->id()); 4363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(return_value); 4364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for bailout, as trying to inline might fail due to bailout 4368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // during hydrogen processing. 4369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call = new HCallKnownGlobal(expr->target(), argument_count); 4372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(new HGlobalObject); 4374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgumentList(expr->arguments()); 4375b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4376b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4377b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call = new HCallGlobal(var->name(), argument_count); 4378b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4379b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4380b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(new HGlobalReceiver); 4382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgumentList(expr->arguments()); 4383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4384b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4385b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call = new HCallFunction(argument_count); 4386b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4387b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4388b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4389b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 4390b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ProcessCall(call); 4391b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(call, expr->id()); 4392b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4393b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4394b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4395b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallNew(CallNew* expr) { 4396b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The constructor function is also used as the receiver argument to the 4397b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // JS construct call builtin. 4398b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgument(expr->expression()); 4399b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4400b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgumentList(expr->arguments()); 4401b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4402b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4403b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length() + 1; // Plus constructor. 4404b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCall* call = new HCallNew(argument_count); 4405b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(expr->position()); 4406b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ProcessCall(call); 4407b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(call, expr->id()); 4408b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4409b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4410b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4411b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for generating inlined runtime functions. 4412b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4413b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Lookup table for generators for runtime calls that are generated inline. 4414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Elements of the table are member pointers to functions of HGraphBuilder. 4415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize) \ 4416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch &HGraphBuilder::Generate##Name, 4417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst HGraphBuilder::InlineFunctionGenerator 4419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraphBuilder::kInlineFunctionGenerators[] = { 4420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 4421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch INLINE_RUNTIME_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS) 4422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch}; 4423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef INLINE_FUNCTION_GENERATOR_ADDRESS 4424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCallRuntime(CallRuntime* expr) { 4427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = expr->name(); 4428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (name->IsEqualTo(CStrVector("_Log"))) { 4429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(graph()->GetConstantUndefined()); 4430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Runtime::Function* function = expr->function(); 4434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->is_jsruntime()) { 4435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("call to a JavaScript runtime function"); 4436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(function != NULL); 4438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitArgumentList(expr->arguments()); 4440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CHECK_BAILOUT; 4441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count = expr->arguments()->length(); 4443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (function->intrinsic_type == Runtime::INLINE) { 4444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(name->length() > 0); 4445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(name->Get(0) == '_'); 4446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Call to an inline function. 4447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int lookup_index = static_cast<int>(function->function_id) - 4448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<int>(Runtime::kFirstInlineFunction); 4449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(lookup_index >= 0); 4450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(static_cast<size_t>(lookup_index) < 4451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ARRAY_SIZE(kInlineFunctionGenerators)); 4452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index]; 4453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Call the inline code generator using the pointer-to-member. 4455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (this->*generator)(argument_count, expr->id()); 4456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(function->intrinsic_type == Runtime::RUNTIME); 4458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCall* call = new HCallRuntime(name, expr->function(), argument_count); 4459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch call->set_position(RelocInfo::kNoPosition); 4460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ProcessCall(call); 4461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(call, expr->id()); 4462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 4467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Value op = expr->op(); 4468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::VOID) { 4469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_EFFECT(expr->expression()); 4470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(graph()->GetConstantUndefined()); 4471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::DELETE) { 4472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = expr->expression()->AsProperty(); 4473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop == NULL && var == NULL) { 4475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Result of deleting non-property, non-variable reference is true. 4476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Evaluate the subexpression for side effects. 4477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_EFFECT(expr->expression()); 4478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(graph()->GetConstantTrue()); 4479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (var != NULL && 4480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch !var->is_global() && 4481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch var->AsSlot() != NULL && 4482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch var->AsSlot()->type() != Slot::LOOKUP) { 4483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Result of deleting non-global, non-dynamic variables is false. 4484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The subexpression does not have side effects. 4485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(graph()->GetConstantFalse()); 4486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (prop != NULL) { 4487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->obj()); 4488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->key()); 4489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = Pop(); 4490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Pop(); 4491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(new HDeleteProperty(obj, key), 4492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->id()); 4493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (var->is_global()) { 4494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("delete with global variable"); 4495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("delete with non-global variable"); 4497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::NOT) { 4499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (ast_context()->IsTest()) { 4500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestContext* context = TestContext::cast(ast_context()); 4501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VisitForControl(expr->expression(), 4502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context->if_false(), 4503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch context->if_true()); 4504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* true_graph = CreateEmptySubgraph(); 4506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* false_graph = CreateEmptySubgraph(); 4507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_CONTROL(expr->expression(), 4508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_graph->entry_block(), 4509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_graph->entry_block()); 4510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_graph->entry_block()->SetJoinId(expr->expression()->id()); 4511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch true_graph->environment()->Push(graph_->GetConstantTrue()); 4512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_graph->entry_block()->SetJoinId(expr->expression()->id()); 4514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch false_graph->environment()->Push(graph_->GetConstantFalse()); 4515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->AppendJoin(true_graph, false_graph, expr); 4517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 4518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::BIT_NOT || op == Token::SUB) { 4520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->expression()); 4521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 4522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 4523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (op) { 4524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_NOT: 4525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HBitNot(value); 4526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SUB: 4528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HMul(graph_->GetConstantMinus1(), value); 4529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 4531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 4532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 4535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::TYPEOF) { 4536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->expression()); 4537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 4538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(new HTypeof(value), expr->id()); 4539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("Value: unsupported unary operation"); 4541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitIncrementOperation(IncrementOperation* expr) { 4546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // IncrementOperation is never visited by the visitor. It only 4547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // occurs as a subexpression of CountOperation. 4548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 4549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildIncrement(HValue* value, bool increment) { 4553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* delta = increment 4554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? graph_->GetConstant1() 4555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : graph_->GetConstantMinus1(); 4556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = new HAdd(value, delta); 4557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssumeRepresentation(instr, Representation::Integer32()); 4558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 4559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCountOperation(CountOperation* expr) { 4563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch IncrementOperation* increment = expr->increment(); 4564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Expression* target = increment->expression(); 4565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VariableProxy* proxy = target->AsVariableProxy(); 4566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = proxy->AsVariable(); 4567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Property* prop = target->AsProperty(); 4568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(var == NULL || prop == NULL); 4569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool inc = expr->op() == Token::INC; 4570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var != NULL) { 4572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!var->is_global() && !var->IsStackAllocated()) { 4573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("non-stack/non-global variable in count operation"); 4574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(target); 4577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Match the full code generator stack by simulating an extra stack 4579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // element for postfix operations in a non-effect context. 4580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); 4581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* before = has_extra ? Top() : Pop(); 4582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* after = BuildIncrement(before, inc); 4583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(after); 4584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Push(after); 4585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var->is_global()) { 4587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HandleGlobalVariableAssignment(var, 4588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch after, 4589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->position(), 4590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch expr->AssignmentId()); 4591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(var->IsStackAllocated()); 4593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Bind(var, after); 4594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(has_extra ? 2 : 1); 4596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (prop != NULL) { 4599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prop->RecordTypeFeedback(oracle()); 4600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->key()->IsPropertyName()) { 4602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Named property. 4603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Match the full code generator stack by simulating an extra stack 4605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // element for postfix operations in a non-effect context. 4606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); 4607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (has_extra) Push(graph_->GetConstantUndefined()); 4608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->obj()); 4610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = Top(); 4611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* load = NULL; 4613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (prop->IsMonomorphic()) { 4614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); 4615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<Map> map = prop->GetReceiverTypes()->first(); 4616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamed(obj, prop, map, name); 4617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch load = BuildLoadNamedGeneric(obj, prop); 4619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 4621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (load->HasSideEffects()) AddSimulate(increment->id()); 4622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* before = Pop(); 4624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is no deoptimization to after the increment, so we don't need 4625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // to simulate the expression stack after this instruction. 4626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* after = BuildIncrement(before, inc); 4627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(after); 4628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* store = BuildStoreNamed(obj, after, prop); 4630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 4631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Overwrite the receiver in the bailout environment with the result 4633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // of the operation, and the placeholder with the original value if 4634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // necessary. 4635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(0, after); 4636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (has_extra) environment()->SetExpressionStackAt(1, before); 4637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(has_extra ? 2 : 1); 4639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Keyed property. 4644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Match the full code generator stack by simulate an extra stack element 4646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // for postfix operations in a non-effect context. 4647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool has_extra = expr->is_postfix() && !ast_context()->IsEffect(); 4648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (has_extra) Push(graph_->GetConstantUndefined()); 4649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->obj()); 4651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(prop->key()); 4652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* obj = environment()->ExpressionStackAt(1); 4653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* key = environment()->ExpressionStackAt(0); 4654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_fast_elements = prop->IsMonomorphic() && 4656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch prop->GetMonomorphicReceiverType()->has_fast_elements(); 4657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* load = is_fast_elements 4659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? BuildLoadKeyedFastElement(obj, key, prop) 4660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : BuildLoadKeyedGeneric(obj, key); 4661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushAndAdd(load); 4662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (load->HasSideEffects()) AddSimulate(increment->id()); 4663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* before = Pop(); 4665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is no deoptimization to after the increment, so we don't need 4666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // to simulate the expression stack after this instruction. 4667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* after = BuildIncrement(before, inc); 4668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(after); 4669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* store = is_fast_elements 4671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ? BuildStoreKeyedFastElement(obj, key, after, prop) 4672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : new HStoreKeyedGeneric(obj, key, after); 4673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(store); 4674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Drop the key from the bailout environment. Overwrite the receiver 4676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // with the result of the operation, and the placeholder with the 4677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // original value if necessary. 4678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(1); 4679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment()->SetExpressionStackAt(0, after); 4680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (has_extra) environment()->SetExpressionStackAt(1, before); 4681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (store->HasSideEffects()) AddSimulate(expr->AssignmentId()); 4682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Drop(has_extra ? 2 : 1); 4683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(expr->is_postfix() ? before : after); 4685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("invalid lhs in count operation"); 4689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 4694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left, 4695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right) { 4696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 4697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (expr->op()) { 4698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::ADD: 4699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HAdd(left, right); 4700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SUB: 4702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HSub(left, right); 4703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::MUL: 4705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HMul(left, right); 4706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::MOD: 4708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HMod(left, right); 4709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::DIV: 4711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HDiv(left, right); 4712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_XOR: 4714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HBitXor(left, right); 4715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_AND: 4717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HBitAnd(left, right); 4718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::BIT_OR: 4720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HBitOr(left, right); 4721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SAR: 4723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HSar(left, right); 4724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SHR: 4726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HShr(left, right); 4727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::SHL: 4729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HShl(left, right); 4730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 4732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); 4733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TypeInfo info = oracle()->BinaryType(expr, TypeFeedbackOracle::RESULT); 4735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // If we hit an uninitialized binary op stub we will get type info 4736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // for a smi operation. If one of the operands is a constant string 4737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // do not generate code assuming it is a smi operation. 4738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsSmi() && 4739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || 4740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { 4741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 4742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_representation) { 4744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic()); 4745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AssumeRepresentation(instr, ToRepresentation(info)); 4747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return instr; 4748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check for the form (%_ClassOf(foo) === 'BarClass'). 4752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochstatic bool IsClassOfTest(CompareOperation* expr) { 4753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->op() != Token::EQ_STRICT) return false; 4754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CallRuntime* call = expr->left()->AsCallRuntime(); 4755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (call == NULL) return false; 4756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* literal = expr->right()->AsLiteral(); 4757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (literal == NULL) return false; 4758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!literal->handle()->IsString()) return false; 4759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 4760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(call->arguments()->length() == 1); 4761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return true; 4762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 4766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (expr->op() == Token::COMMA) { 4767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_EFFECT(expr->left()); 4768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Visit the right subexpression in the same AST context as the entire 4769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // expression. 4770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr->right()); 4771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (expr->op() == Token::AND || expr->op() == Token::OR) { 4773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_logical_and = (expr->op() == Token::AND); 4774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (ast_context()->IsTest()) { 4775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TestContext* context = TestContext::cast(ast_context()); 4776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Translate left subexpression. 4777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* eval_right = graph()->CreateBasicBlock(); 4778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_logical_and) { 4779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_CONTROL(expr->left(), eval_right, context->if_false()); 4780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_CONTROL(expr->left(), context->if_true(), eval_right); 4782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch eval_right->SetJoinId(expr->RightId()); 4784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Translate right subexpression by visiting it in the same AST 4786b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // context as the entire expression. 4787b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch subgraph()->set_exit_block(eval_right); 4788b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Visit(expr->right()); 4789b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4790b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4791b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->left()); 4792b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(current_subgraph_->HasExit()); 4793b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4794b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Top(); 4795b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* environment_copy = environment()->Copy(); 4796b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch environment_copy->Pop(); 4797b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HSubgraph* right_subgraph; 4798b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch right_subgraph = CreateBranchSubgraph(environment_copy); 4799b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ADD_TO_SUBGRAPH(right_subgraph, expr->right()); 4800b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->AppendOptional(right_subgraph, is_logical_and, left); 4801b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_subgraph_->exit_block()->SetJoinId(expr->id()); 4802b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnValue(Pop()); 4803b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4804b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4805b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4806b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->left()); 4807b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->right()); 4808b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4809b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 4810b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 4811b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = BuildBinaryOperation(expr, left, right); 4812b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 4813b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 4814b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4815b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4816b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4817b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4818b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) { 4819b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value->CheckFlag(HValue::kFlexibleRepresentation)) { 4820b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_representation) { 4821b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Assume representation for %s to be %s (%d)\n", 4822b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->Mnemonic(), 4823b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch r.Mnemonic(), 4824b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_->GetMaximumValueID()); 4825b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4826b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->ChangeRepresentation(r); 4827b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The representation of the value is dictated by type feedback. 4828b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch value->ClearFlag(HValue::kFlexibleRepresentation); 4829b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (FLAG_trace_representation) { 4830b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("No representation assumed\n"); 4831b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4832b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4833b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4834b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4835b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochRepresentation HGraphBuilder::ToRepresentation(TypeInfo info) { 4836b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsSmi()) return Representation::Integer32(); 4837b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsInteger32()) return Representation::Integer32(); 4838b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsDouble()) return Representation::Double(); 4839b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (info.IsNumber()) return Representation::Double(); 4840b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return Representation::Tagged(); 4841b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4842b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4843b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4844b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareOperation(CompareOperation* expr) { 4845b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (IsClassOfTest(expr)) { 4846b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch CallRuntime* call = expr->left()->AsCallRuntime(); 4847b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(call->arguments()->at(0)); 4848b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 4849b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* literal = expr->right()->AsLiteral(); 4850b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> rhs = Handle<String>::cast(literal->handle()); 4851b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = new HClassOfTest(value, rhs); 4852b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 4853b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 4854b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4855b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4856b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4857b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Check for the pattern: typeof <expression> == <string literal>. 4858b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UnaryOperation* left_unary = expr->left()->AsUnaryOperation(); 4859b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Literal* right_literal = expr->right()->AsLiteral(); 4860b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if ((expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT) && 4861b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch left_unary != NULL && left_unary->op() == Token::TYPEOF && 4862b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch right_literal != NULL && right_literal->handle()->IsString()) { 4863b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(left_unary->expression()); 4864b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 4865b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = new HTypeofIs(left, 4866b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String>::cast(right_literal->handle())); 4867b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 4868b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 4869b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 4870b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4871b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4872b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->left()); 4873b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->right()); 4874b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4875b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 4876b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 4877b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Token::Value op = expr->op(); 4878b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4879b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TypeInfo info = oracle()->CompareType(expr, TypeFeedbackOracle::RESULT); 4880b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instr = NULL; 4881b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op == Token::INSTANCEOF) { 4882086aeeaae12517475c22695a200be45495516549Ben Murdoch // Check to see if the rhs of the instanceof is a global function not 4883086aeeaae12517475c22695a200be45495516549Ben Murdoch // residing in new space. If it is we assume that the function will stay the 4884086aeeaae12517475c22695a200be45495516549Ben Murdoch // same. 4885086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<JSFunction> target = Handle<JSFunction>::null(); 4886086aeeaae12517475c22695a200be45495516549Ben Murdoch Variable* var = expr->right()->AsVariableProxy()->AsVariable(); 4887086aeeaae12517475c22695a200be45495516549Ben Murdoch bool global_function = (var != NULL) && var->is_global() && !var->is_this(); 4888086aeeaae12517475c22695a200be45495516549Ben Murdoch CompilationInfo* info = graph()->info(); 4889086aeeaae12517475c22695a200be45495516549Ben Murdoch if (global_function && 4890086aeeaae12517475c22695a200be45495516549Ben Murdoch info->has_global_object() && 4891086aeeaae12517475c22695a200be45495516549Ben Murdoch !info->global_object()->IsAccessCheckNeeded()) { 4892086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<String> name = var->name(); 4893086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<GlobalObject> global(info->global_object()); 4894086aeeaae12517475c22695a200be45495516549Ben Murdoch LookupResult lookup; 4895086aeeaae12517475c22695a200be45495516549Ben Murdoch global->Lookup(*name, &lookup); 4896086aeeaae12517475c22695a200be45495516549Ben Murdoch if (lookup.IsProperty() && 4897086aeeaae12517475c22695a200be45495516549Ben Murdoch lookup.type() == NORMAL && 4898086aeeaae12517475c22695a200be45495516549Ben Murdoch lookup.GetValue()->IsJSFunction()) { 4899086aeeaae12517475c22695a200be45495516549Ben Murdoch Handle<JSFunction> candidate(JSFunction::cast(lookup.GetValue())); 4900086aeeaae12517475c22695a200be45495516549Ben Murdoch // If the function is in new space we assume it's more likely to 4901086aeeaae12517475c22695a200be45495516549Ben Murdoch // change and thus prefer the general IC code. 4902086aeeaae12517475c22695a200be45495516549Ben Murdoch if (!Heap::InNewSpace(*candidate)) { 4903086aeeaae12517475c22695a200be45495516549Ben Murdoch target = candidate; 4904086aeeaae12517475c22695a200be45495516549Ben Murdoch } 4905086aeeaae12517475c22695a200be45495516549Ben Murdoch } 4906086aeeaae12517475c22695a200be45495516549Ben Murdoch } 4907086aeeaae12517475c22695a200be45495516549Ben Murdoch 4908086aeeaae12517475c22695a200be45495516549Ben Murdoch // If the target is not null we have found a known global function that is 4909086aeeaae12517475c22695a200be45495516549Ben Murdoch // assumed to stay the same for this instanceof. 4910086aeeaae12517475c22695a200be45495516549Ben Murdoch if (target.is_null()) { 4911086aeeaae12517475c22695a200be45495516549Ben Murdoch instr = new HInstanceOf(left, right); 4912086aeeaae12517475c22695a200be45495516549Ben Murdoch } else { 4913086aeeaae12517475c22695a200be45495516549Ben Murdoch AddInstruction(new HCheckFunction(right, target)); 4914086aeeaae12517475c22695a200be45495516549Ben Murdoch instr = new HInstanceOfKnownGlobal(left, target); 4915086aeeaae12517475c22695a200be45495516549Ben Murdoch } 4916b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (op == Token::IN) { 4917b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("Unsupported comparison: in"); 4918b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (info.IsNonPrimitive()) { 4919b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch switch (op) { 4920b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ: 4921b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch case Token::EQ_STRICT: { 49229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block AddInstruction(new HCheckNonSmi(left)); 4923b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(left)); 49249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block AddInstruction(new HCheckNonSmi(right)); 4925b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AddInstruction(HCheckInstanceType::NewIsJSObjectOrJSFunction(right)); 4926b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = new HCompareJSObjectEq(left, right); 4927b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4928b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4929b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch default: 4930b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("Unsupported non-primitive compare"); 4931b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch break; 4932b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4933b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 4934b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCompare* compare = new HCompare(left, right, op); 4935b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Representation r = ToRepresentation(info); 4936b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch compare->SetInputRepresentation(r); 4937b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr = compare; 4938b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4939b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instr->set_position(expr->position()); 4940b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(instr, expr->id()); 4941b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4942b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4943b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4944b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitCompareToNull(CompareToNull* expr) { 4945b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch VISIT_FOR_VALUE(expr->expression()); 4946b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4947b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 4948b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HIsNull* compare = new HIsNull(value, expr->is_strict()); 4949b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(compare, expr->id()); 4950b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4951b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4952b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4953b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitThisFunction(ThisFunction* expr) { 4954b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("ThisFunction"); 4955b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4956b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4957b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4958b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::VisitDeclaration(Declaration* decl) { 4959b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // We allow only declarations that do not require code generation. 4960b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The following all require code generation: global variables and 4961b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // functions, variables with slot type LOOKUP, declarations with 4962b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // mode CONST, and functions. 4963b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Variable* var = decl->proxy()->var(); 4964b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Slot* slot = var->AsSlot(); 4965b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (var->is_global() || 4966b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch (slot != NULL && slot->type() == Slot::LOOKUP) || 4967b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch decl->mode() == Variable::CONST || 4968b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch decl->fun() != NULL) { 4969b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("unsupported declaration"); 4970b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 4971b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4972b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4973b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4974b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Generators for inline runtime functions. 4975b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for types. 4976b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsSmi(int argument_count, int ast_id) { 4977b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 1); 4978b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 4979b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HIsSmi* result = new HIsSmi(value); 4980b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 4981b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4982b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4983b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4984b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsSpecObject(int argument_count, int ast_id) { 4985b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 1); 4986b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 4987b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HHasInstanceType* result = 4988b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HHasInstanceType(value, FIRST_JS_OBJECT_TYPE, LAST_TYPE); 4989b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 4990b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4991b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4992b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 4993b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsFunction(int argument_count, int ast_id) { 4994b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 1); 4995b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 4996b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HHasInstanceType* result = new HHasInstanceType(value, JS_FUNCTION_TYPE); 4997b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 4998b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 4999b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5000b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5001b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateHasCachedArrayIndex(int argument_count, 5002b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 5003b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 1); 5004b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 5005b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HHasCachedArrayIndex* result = new HHasCachedArrayIndex(value); 5006b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5007b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5008b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5009b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5010b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsArray(int argument_count, int ast_id) { 5011b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 1); 5012b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 5013b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HHasInstanceType* result = new HHasInstanceType(value, JS_ARRAY_TYPE); 5014b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5015b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5016b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5017b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5018b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsRegExp(int argument_count, int ast_id) { 5019b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 1); 5020b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 5021b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HHasInstanceType* result = new HHasInstanceType(value, JS_REGEXP_TYPE); 5022b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5023b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5024b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5025b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5026b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsObject(int argument_count, int ast_id) { 5027b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 1); 5028b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5029b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 5030b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HIsObject* test = new HIsObject(value); 5031b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(test, ast_id); 5032b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5033b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5034b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5035b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsNonNegativeSmi(int argument_count, 5036b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 5037b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: IsNonNegativeSmi"); 5038b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5039b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5040b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5041b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsUndetectableObject(int argument_count, 5042b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 5043b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: IsUndetectableObject"); 5044b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5045b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5046b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5047b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf( 5048b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int argument_count, 5049b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 5050b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: IsStringWrapperSafeForDefaultValueOf"); 5051b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5052b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5053b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5054b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Support for construct call checks. 5055b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsConstructCall(int argument_count, int ast_id) { 5056b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: IsConstructCall"); 5057b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5058b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5059b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5060b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for arguments.length and arguments[?]. 5061b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateArgumentsLength(int argument_count, int ast_id) { 5062b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 0); 5063b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* elements = AddInstruction(new HArgumentsElements); 5064b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HArgumentsLength* result = new HArgumentsLength(elements); 5065b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5066b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5067b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5068b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5069b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateArguments(int argument_count, int ast_id) { 5070b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 1); 5071b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* index = Pop(); 5072b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* elements = AddInstruction(new HArgumentsElements); 5073b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* length = AddInstruction(new HArgumentsLength(elements)); 5074b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HAccessArgumentsAt* result = new HAccessArgumentsAt(elements, length, index); 5075b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5076b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5077b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5078b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5079b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for accessing the class and value fields of an object. 5080b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateClassOf(int argument_count, int ast_id) { 5081b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // The special form detected by IsClassOfTest is detected before we get here 5082b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // and does not cause a bailout. 5083b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: ClassOf"); 5084b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5085b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5086b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5087b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateValueOf(int argument_count, int ast_id) { 5088b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 1); 5089b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = Pop(); 5090b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValueOf* result = new HValueOf(value); 5091b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5092b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5093b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5094b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5095b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateSetValueOf(int argument_count, int ast_id) { 5096b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: SetValueOf"); 5097b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5098b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5099b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5100b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for charCodeAt(n). 5101b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateStringCharCodeAt(int argument_count, int ast_id) { 5102b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: StringCharCodeAt"); 5103b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5104b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5105b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5106b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n]. 5107b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateStringCharFromCode(int argument_count, 5108b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 5109b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: StringCharFromCode"); 5110b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5111b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5112b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5113b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for string.charAt(n) and string[n]. 5114b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateStringCharAt(int argument_count, int ast_id) { 5115b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(2, argument_count); 5116b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushArgumentsForStubCall(argument_count); 5117b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = new HCallStub(CodeStub::StringCharAt, argument_count); 5118b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5119b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5120b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5121b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5122b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for object equality testing. 5123b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateObjectEquals(int argument_count, int ast_id) { 5124b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(argument_count == 2); 5125b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 5126b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 5127b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCompareJSObjectEq* result = new HCompareJSObjectEq(left, right); 5128b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5129b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5130b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5131b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5132b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateLog(int argument_count, int ast_id) { 5133b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UNREACHABLE(); // We caught this in VisitCallRuntime. 5134b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5135b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5136b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5137b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for Math.random(). 5138b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateRandomHeapNumber(int argument_count, int ast_id) { 5139b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: RandomHeapNumber"); 5140b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5141b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5142b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5143b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringAdd. 5144b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateStringAdd(int argument_count, int ast_id) { 5145b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(2, argument_count); 5146b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushArgumentsForStubCall(argument_count); 5147b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = new HCallStub(CodeStub::StringAdd, argument_count); 5148b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5149b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5150b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5151b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5152b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for SubString. 5153b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateSubString(int argument_count, int ast_id) { 5154b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(3, argument_count); 5155b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushArgumentsForStubCall(argument_count); 5156b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = new HCallStub(CodeStub::SubString, argument_count); 5157b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5158b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5159b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5160b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5161b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for StringCompare. 5162b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateStringCompare(int argument_count, int ast_id) { 5163b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(2, argument_count); 5164b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushArgumentsForStubCall(argument_count); 5165b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = new HCallStub(CodeStub::StringCompare, argument_count); 5166b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5167b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5168b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5169b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5170b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for direct calls from JavaScript to native RegExp code. 5171b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateRegExpExec(int argument_count, int ast_id) { 5172b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(4, argument_count); 5173b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushArgumentsForStubCall(argument_count); 5174b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = new HCallStub(CodeStub::RegExpExec, argument_count); 5175b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5176b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5177b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5178b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5179b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Construct a RegExp exec result with two in-object properties. 5180b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateRegExpConstructResult(int argument_count, 5181b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 5182b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(3, argument_count); 5183b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushArgumentsForStubCall(argument_count); 5184b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = 5185b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HCallStub(CodeStub::RegExpConstructResult, argument_count); 5186b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5187b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5188b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5189b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5190b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Support for fast native caches. 5191b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateGetFromCache(int argument_count, int ast_id) { 5192b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: GetFromCache"); 5193b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5194b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5195b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5196b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast support for number to string. 5197b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateNumberToString(int argument_count, int ast_id) { 5198b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(1, argument_count); 5199b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushArgumentsForStubCall(argument_count); 5200b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = new HCallStub(CodeStub::NumberToString, argument_count); 5201b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5202b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5203b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5204b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5205b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast swapping of elements. Takes three expressions, the object and two 5206b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// indices. This should only be used if the indices are known to be 5207b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// non-negative and within bounds of the elements array at the call site. 5208b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateSwapElements(int argument_count, int ast_id) { 5209b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: SwapElements"); 5210b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5211b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5212b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5213b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call for custom callbacks. 5214b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateCallFunction(int argument_count, int ast_id) { 5215b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: CallFunction"); 5216b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5217b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5218b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5219b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Fast call to math functions. 5220b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateMathPow(int argument_count, int ast_id) { 5221b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(2, argument_count); 5222b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* right = Pop(); 5223b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* left = Pop(); 5224b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPower* result = new HPower(left, right); 5225b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5226b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5227b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5228b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5229b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateMathSin(int argument_count, int ast_id) { 5230b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(1, argument_count); 5231b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushArgumentsForStubCall(argument_count); 5232b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = 5233b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HCallStub(CodeStub::TranscendentalCache, argument_count); 5234b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::SIN); 5235b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5236b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5237b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5238b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5239b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateMathCos(int argument_count, int ast_id) { 5240b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(1, argument_count); 5241b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushArgumentsForStubCall(argument_count); 5242b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = 5243b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HCallStub(CodeStub::TranscendentalCache, argument_count); 5244b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::COS); 5245b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5246b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5247b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5248b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5249b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateMathLog(int argument_count, int ast_id) { 5250b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT_EQ(1, argument_count); 5251b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PushArgumentsForStubCall(argument_count); 5252b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HCallStub* result = 5253b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new HCallStub(CodeStub::TranscendentalCache, argument_count); 5254b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->set_transcendental_type(TranscendentalCache::LOG); 5255b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_context()->ReturnInstruction(result, ast_id); 5256b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5257b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5258b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5259b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateMathSqrt(int argument_count, int ast_id) { 5260b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: MathSqrt"); 5261b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5262b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5263b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5264b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch// Check whether two RegExps are equivalent 5265b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateIsRegExpEquivalent(int argument_count, 5266b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 5267b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: IsRegExpEquivalent"); 5268b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5269b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5270b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5271b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateGetCachedArrayIndex(int argument_count, 5272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 5273b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: GetCachedArrayIndex"); 5274b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5276b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HGraphBuilder::GenerateFastAsciiArrayJoin(int argument_count, 5278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int ast_id) { 5279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch BAILOUT("inlined runtime function: FastAsciiArrayJoin"); 5280b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5281b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5283b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef BAILOUT 5284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef CHECK_BAILOUT 5285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef VISIT_FOR_EFFECT 5286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef VISIT_FOR_VALUE 5287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#undef ADD_TO_SUBGRAPH 5288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(HEnvironment* outer, 5291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Scope* scope, 5292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<JSFunction> closure) 5293b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : closure_(closure), 5294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_(0), 5295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch assigned_variables_(4), 5296b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_(0), 5297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_(0), 5298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_(outer), 5299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pop_count_(0), 5300b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch push_count_(0), 5301b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_id_(AstNode::kNoNumber) { 5302b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Initialize(scope->num_parameters() + 1, scope->num_stack_slots(), 0); 5303b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5304b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5305b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5306b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment::HEnvironment(const HEnvironment* other) 5307b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch : values_(0), 5308b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch assigned_variables_(0), 5309b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_(0), 5310b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_(0), 5311b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer_(NULL), 5312b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch pop_count_(0), 5313b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch push_count_(0), 5314b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ast_id_(other->ast_id()) { 5315b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Initialize(other); 5316b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5317b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5318b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5319b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::Initialize(int parameter_count, 5320b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int local_count, 5321b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int stack_height) { 5322b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parameter_count_ = parameter_count; 5323b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch local_count_ = local_count; 5324b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5325b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Avoid reallocating the temporaries' backing store on the first Push. 5326b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int total = parameter_count + local_count + stack_height; 5327b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch values_.Initialize(total + 4); 5328b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < total; ++i) values_.Add(NULL); 5329b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5330b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5331b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 53329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Initialize(const HEnvironment* other) { 53339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block closure_ = other->closure(); 53349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_.AddAll(other->values_); 53359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block assigned_variables_.AddAll(other->assigned_variables_); 53369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block parameter_count_ = other->parameter_count_; 53379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block local_count_ = other->local_count_; 53389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (other->outer_ != NULL) outer_ = other->outer_->Copy(); // Deep copy. 53399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block pop_count_ = other->pop_count_; 53409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block push_count_ = other->push_count_; 53419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ast_id_ = other->ast_id_; 53429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 53439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 53449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 5345b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) { 5346b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(!block->IsLoopHeader()); 5347b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(values_.length() == other->values_.length()); 5348b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5349b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int length = values_.length(); 5350b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < length; ++i) { 5351b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* value = values_[i]; 5352b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (value != NULL && value->IsPhi() && value->block() == block) { 5353b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is already a phi for the i'th value. 5354b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = HPhi::cast(value); 5355b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Assert index is correct and that we haven't missed an incoming edge. 5356b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->merged_index() == i); 5357b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(phi->OperandCount() == block->predecessors()->length()); 5358b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(other->values_[i]); 5359b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (values_[i] != other->values_[i]) { 5360b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // There is a fresh value on the incoming edge, a phi is needed. 5361b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(values_[i] != NULL && other->values_[i] != NULL); 5362b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = new HPhi(i); 5363b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* old_value = values_[i]; 5364b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < block->predecessors()->length(); j++) { 5365b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(old_value); 5366b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5367b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(other->values_[i]); 5368b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch this->values_[i] = phi; 5369b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch block->AddPhi(phi); 5370b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5371b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5372b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5373b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5374b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 53759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Bind(int index, HValue* value) { 53769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(value != NULL); 53779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!assigned_variables_.Contains(index)) { 53789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block assigned_variables_.Add(index); 53799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 53809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_[index] = value; 5381b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5382b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5383b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 53849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::HasExpressionAt(int index) const { 53859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return index >= parameter_count_ + local_count_; 53869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 53879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 53889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 53899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockbool HEnvironment::ExpressionStackIsEmpty() const { 53909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int first_expression = parameter_count() + local_count(); 53919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(length() >= first_expression); 53929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return length() == first_expression; 53939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 53949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 53959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 53969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) { 53979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int count = index_from_top + 1; 53989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index = values_.length() - count; 53999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(HasExpressionAt(index)); 54009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // The push count must include at least the element in question or else 54019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // the new value will not be included in this environment's history. 54029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (push_count_ < count) { 54039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // This is the same effect as popping then re-pushing 'count' elements. 54049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block pop_count_ += (count - push_count_); 54059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block push_count_ = count; 54069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 54079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block values_[index] = value; 54089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 54099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 54109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 54119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid HEnvironment::Drop(int count) { 54129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = 0; i < count; ++i) { 54139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Pop(); 5414b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5415b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5416b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5417b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5418b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::Copy() const { 5419b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new HEnvironment(this); 5420b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5421b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5422b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5423b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyWithoutHistory() const { 5424b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* result = Copy(); 5425b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch result->ClearHistory(); 5426b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return result; 5427b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5428b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5429b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5430b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const { 5431b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* new_env = Copy(); 5432b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < values_.length(); ++i) { 5433b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = new HPhi(i); 5434b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->AddInput(values_[i]); 5435b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_env->values_[i] = phi; 5436b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch loop_header->AddPhi(phi); 5437b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5438b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch new_env->ClearHistory(); 5439b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return new_env; 5440b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5441b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5442b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5443b0fe1620dcb4135ac3ab2d66ff93072373911299Ben MurdochHEnvironment* HEnvironment::CopyForInlining(Handle<JSFunction> target, 5444b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch FunctionLiteral* function, 5445b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch bool is_speculative, 5446b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HConstant* undefined) const { 5447b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Outer environment is a copy of this one without the arguments. 5448b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int arity = function->scope()->num_parameters(); 5449b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* outer = Copy(); 5450b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer->Drop(arity + 1); // Including receiver. 5451b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch outer->ClearHistory(); 5452b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HEnvironment* inner = new HEnvironment(outer, function->scope(), target); 5453b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Get the argument values from the original environment. 5454b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (is_speculative) { 5455b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i <= arity; ++i) { // Include receiver. 5456b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* push = ExpressionStackAt(arity - i); 5457b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inner->SetValueAt(i, push); 5458b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5459b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5460b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i <= arity; ++i) { // Include receiver. 5461b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inner->SetValueAt(i, ExpressionStackAt(arity - i)); 5462b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5463b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5464b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5465b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Initialize the stack-allocated locals to undefined. 5466b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int local_base = arity + 1; 5467b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int local_count = function->scope()->num_stack_slots(); 5468b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < local_count; ++i) { 5469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inner->SetValueAt(local_base + i, undefined); 5470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch inner->set_ast_id(function->id()); 5473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return inner; 5474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5475b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintTo(StringStream* stream) { 54789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = 0; i < length(); i++) { 5479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (i == 0) stream->Add("parameters\n"); 5480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (i == parameter_count()) stream->Add("locals\n"); 5481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (i == parameter_count() + local_count()) stream->Add("expressions"); 5482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HValue* val = values_.at(i); 5483b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("%d: ", i); 5484b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (val != NULL) { 5485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch val->PrintNameTo(stream); 5486b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5487b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("NULL"); 5488b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch stream->Add("\n"); 5490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5491b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5493b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5494b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HEnvironment::PrintToStd() { 5495b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HeapStringAllocator string_allocator; 5496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch StringStream trace(&string_allocator); 5497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintTo(&trace); 5498b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("%s", *trace.ToCString()); 5499b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5500b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5501b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5502b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceCompilation(FunctionLiteral* function) { 5503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "compilation"); 5504b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Handle<String> name = function->debug_name(); 5505b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", *name->ToCString()); 5506b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("method", *name->ToCString()); 5507b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintLongProperty("date", static_cast<int64_t>(OS::TimeCurrentMillis())); 5508b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5509b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5511b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLithium(const char* name, LChunk* chunk) { 5512b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Trace(name, chunk->graph(), chunk); 5513b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5514b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5515b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5516b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceHydrogen(const char* name, HGraph* graph) { 5517b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Trace(name, graph, NULL); 5518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5521b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) { 5522b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "cfg"); 5523b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", name); 5524b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<HBasicBlock*>* blocks = graph->blocks(); 5525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < blocks->length(); i++) { 5526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HBasicBlock* current = blocks->at(i); 5527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag block_tag(this, "block"); 5528b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("name", current->block_id()); 5529b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty("from_bci", -1); 5530b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty("to_bci", -1); 5531b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5532b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (!current->predecessors()->is_empty()) { 5533b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIndent(); 5534b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("predecessors"); 5535b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < current->predecessors()->length(); ++j) { 5536b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id()); 5537b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5538b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("\n"); 5539b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5540b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("predecessors"); 5541b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5542b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5543b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->end() == NULL || current->end()->FirstSuccessor() == NULL) { 5544b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("successors"); 5545b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (current->end()->SecondSuccessor() == NULL) { 5546b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("successors", 5547b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->end()->FirstSuccessor()->block_id()); 5548b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5549b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("successors", 5550b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->end()->FirstSuccessor()->block_id(), 5551b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current->end()->SecondSuccessor()->block_id()); 5552b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5553b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5554b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("xhandlers"); 5555b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintEmptyProperty("flags"); 5556b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5557b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current->dominator() != NULL) { 5558b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintBlockProperty("dominator", current->dominator()->block_id()); 5559b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5560b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5561b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk != NULL) { 5562b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int first_index = current->first_instruction_index(); 5563b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_index = current->last_instruction_index(); 5564b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty( 5565b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "first_lir_id", 5566b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(first_index).Value()); 5567b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintIntProperty( 5568b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "last_lir_id", 5569b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(last_index).Value()); 5570b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5571b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5572b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 5573b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag states_tag(this, "states"); 5574b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag locals_tag(this, "locals"); 5575b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int total = current->phis()->length(); 5576b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("size %d\n", total); 5577b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("method \"None\""); 5578b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int j = 0; j < total; ++j) { 5579b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HPhi* phi = current->phis()->at(j); 5580b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d ", phi->merged_index()); 5581b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->PrintNameTo(&trace_); 5582b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" "); 5583b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch phi->PrintTo(&trace_); 5584b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("\n"); 5585b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5586b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5587b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5588b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch { 5589b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag HIR_tag(this, "HIR"); 5590b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HInstruction* instruction = current->first(); 5591b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (instruction != NULL) { 5592b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int bci = 0; 5593b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int uses = instruction->uses()->length(); 5594b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d %d ", bci, uses); 5595b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction->PrintNameTo(&trace_); 5596b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" "); 5597b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction->PrintTo(&trace_); 5598b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" <|@\n"); 5599b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch instruction = instruction->next(); 5600b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5601b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5602b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5603b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5604b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk != NULL) { 5605b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag LIR_tag(this, "LIR"); 5606b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int first_index = current->first_instruction_index(); 5607b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int last_index = current->last_instruction_index(); 5608b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (first_index != -1 && last_index != -1) { 5609b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<LInstruction*>* instructions = chunk->instructions(); 5610b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = first_index; i <= last_index; ++i) { 5611b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LInstruction* linstr = instructions->at(i); 5612b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (linstr != NULL) { 5613b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d ", 5614b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LifetimePosition::FromInstructionIndex(i).Value()); 5615b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch linstr->PrintTo(&trace_); 5616b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" <|@\n"); 5617b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5618b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5619b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5620b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5621b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5622b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5623b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5624b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5625b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) { 5626b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Tag tag(this, "intervals"); 5627b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintStringProperty("name", name); 5628b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5629b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges(); 5630b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < fixed_d->length(); ++i) { 5631b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(fixed_d->at(i), "fixed"); 5632b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5633b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5634b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<LiveRange*>* fixed = allocator->fixed_live_ranges(); 5635b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < fixed->length(); ++i) { 5636b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(fixed->at(i), "fixed"); 5637b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5638b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5639b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges(); 5640b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < live_ranges->length(); ++i) { 5641b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch TraceLiveRange(live_ranges->at(i), "object"); 5642b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5643b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5644b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5645b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5646b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::TraceLiveRange(LiveRange* range, const char* type) { 5647b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range != NULL && !range->IsEmpty()) { 5648b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add("%d %s", range->id(), type); 5649b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range->HasRegisterAssigned()) { 5650b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op = range->CreateAssignedOperand(); 5651b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int assigned_reg = op->index(); 5652b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op->IsDoubleRegister()) { 5653b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"%s\"", 5654b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch DoubleRegister::AllocationIndexToString(assigned_reg)); 5655b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5656b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsRegister()); 5657b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg)); 5658b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5659b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (range->IsSpilled()) { 5660b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op = range->TopLevel()->GetSpillOperand(); 5661b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op->IsDoubleStackSlot()) { 5662b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"double_stack:%d\"", op->index()); 5663b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5664b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch ASSERT(op->IsStackSlot()); 5665b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"stack:%d\"", op->index()); 5666b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5667b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5668b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int parent_index = -1; 5669b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (range->IsChild()) { 5670b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parent_index = range->parent()->id(); 5671b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5672b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch parent_index = range->id(); 5673b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5674b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LOperand* op = range->FirstHint(); 5675b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int hint_index = -1; 5676b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (op != NULL && op->IsUnallocated()) hint_index = op->VirtualRegister(); 5677b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" %d %d", parent_index, hint_index); 5678b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UseInterval* cur_interval = range->first_interval(); 5679b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (cur_interval != NULL) { 5680b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" [%d, %d[", 5681b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval->start().Value(), 5682b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval->end().Value()); 5683b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch cur_interval = cur_interval->next(); 5684b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5685b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5686b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch UsePosition* current_pos = range->first_pos(); 5687b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch while (current_pos != NULL) { 5688b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (current_pos->RegisterIsBeneficial()) { 5689b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" %d M", current_pos->pos().Value()); 5690b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5691b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch current_pos = current_pos->next(); 5692b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5693b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5694b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Add(" \"\"\n"); 5695b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5696b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5697b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5698b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5699b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HTracer::FlushToFile() { 5700b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch AppendChars(filename_, *trace_.ToCString(), trace_.length(), false); 5701b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch trace_.Reset(); 5702b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5703b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5704b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5705b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStatistics::Print() { 5706b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("Timing results:\n"); 5707b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int64_t sum = 0; 5708b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < timing_.length(); ++i) { 5709b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch sum += timing_[i]; 5710b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5711b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5712b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < names_.length(); ++i) { 5713b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("%30s", names_[i]); 5714b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double ms = static_cast<double>(timing_[i]) / 1000; 5715b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch double percent = static_cast<double>(timing_[i]) * 100 / sum; 5716b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF(" - %0.3f ms / %0.3f %% \n", ms, percent); 5717b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5718b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("%30s - %0.3f ms \n", "Sum", static_cast<double>(sum) / 1000); 5719b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("---------------------------------------------------------------\n"); 5720b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch PrintF("%30s - %0.3f ms (%0.1f times slower than full code gen)\n", 5721b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch "Total", 5722b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<double>(total_) / 1000, 5723b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch static_cast<double>(total_) / full_code_gen_); 5724b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5725b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5726b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5727b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HStatistics::SaveTiming(const char* name, int64_t ticks) { 5728b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (name == HPhase::kFullCodeGen) { 5729b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch full_code_gen_ += ticks; 5730b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else if (name == HPhase::kTotal) { 5731b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch total_ += ticks; 5732b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } else { 5733b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch for (int i = 0; i < names_.length(); ++i) { 5734b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (names_[i] == name) { 5735b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch timing_[i] += ticks; 5736b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch return; 5737b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5738b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5739b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch names_.Add(name); 5740b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch timing_.Add(ticks); 5741b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5742b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5743b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5744b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5745b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kFullCodeGen = "Full code generator"; 5746b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochconst char* const HPhase::kTotal = "Total"; 5747b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5748b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5749b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::Begin(const char* name, 5750b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HGraph* graph, 5751b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LChunk* chunk, 5752b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch LAllocator* allocator) { 5753b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch name_ = name; 5754b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch graph_ = graph; 5755b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk_ = chunk; 5756b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch allocator_ = allocator; 5757b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator != NULL && chunk_ == NULL) { 5758b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch chunk_ = allocator->chunk(); 5759b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5760b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_time_hydrogen) start_ = OS::Ticks(); 5761b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5762b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5763b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5764b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdochvoid HPhase::End() const { 5765b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_time_hydrogen) { 5766b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch int64_t end = OS::Ticks(); 5767b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HStatistics::Instance()->SaveTiming(name_, end - start_); 5768b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5769b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5770b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (FLAG_trace_hydrogen) { 5771b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (graph_ != NULL) HTracer::Instance()->TraceHydrogen(name_, graph_); 5772b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk_ != NULL) HTracer::Instance()->TraceLithium(name_, chunk_); 5773b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator_ != NULL) { 5774b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch HTracer::Instance()->TraceLiveRanges(name_, allocator_); 5775b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5776b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 5777b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5778b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#ifdef DEBUG 5779b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (graph_ != NULL) graph_->Verify(); 5780b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (chunk_ != NULL) chunk_->Verify(); 5781b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch if (allocator_ != NULL) allocator_->Verify(); 5782b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch#endif 5783b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 5784b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 5785b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} } // namespace v8::internal 5786