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