Home | History | Annotate | Download | only in src
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "src/hydrogen.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "src/v8.h"
     10 
     11 #include "src/allocation-site-scopes.h"
     12 #include "src/codegen.h"
     13 #include "src/full-codegen.h"
     14 #include "src/hashmap.h"
     15 #include "src/hydrogen-bce.h"
     16 #include "src/hydrogen-bch.h"
     17 #include "src/hydrogen-canonicalize.h"
     18 #include "src/hydrogen-check-elimination.h"
     19 #include "src/hydrogen-dce.h"
     20 #include "src/hydrogen-dehoist.h"
     21 #include "src/hydrogen-environment-liveness.h"
     22 #include "src/hydrogen-escape-analysis.h"
     23 #include "src/hydrogen-gvn.h"
     24 #include "src/hydrogen-infer-representation.h"
     25 #include "src/hydrogen-infer-types.h"
     26 #include "src/hydrogen-load-elimination.h"
     27 #include "src/hydrogen-mark-deoptimize.h"
     28 #include "src/hydrogen-mark-unreachable.h"
     29 #include "src/hydrogen-osr.h"
     30 #include "src/hydrogen-range-analysis.h"
     31 #include "src/hydrogen-redundant-phi.h"
     32 #include "src/hydrogen-removable-simulates.h"
     33 #include "src/hydrogen-representation-changes.h"
     34 #include "src/hydrogen-sce.h"
     35 #include "src/hydrogen-store-elimination.h"
     36 #include "src/hydrogen-uint32-analysis.h"
     37 #include "src/ic/call-optimization.h"
     38 #include "src/ic/ic.h"
     39 // GetRootConstructor
     40 #include "src/ic/ic-inl.h"
     41 #include "src/lithium-allocator.h"
     42 #include "src/parser.h"
     43 #include "src/runtime.h"
     44 #include "src/scopeinfo.h"
     45 #include "src/scopes.h"
     46 #include "src/typing.h"
     47 
     48 #if V8_TARGET_ARCH_IA32
     49 #include "src/ia32/lithium-codegen-ia32.h"  // NOLINT
     50 #elif V8_TARGET_ARCH_X64
     51 #include "src/x64/lithium-codegen-x64.h"  // NOLINT
     52 #elif V8_TARGET_ARCH_ARM64
     53 #include "src/arm64/lithium-codegen-arm64.h"  // NOLINT
     54 #elif V8_TARGET_ARCH_ARM
     55 #include "src/arm/lithium-codegen-arm.h"  // NOLINT
     56 #elif V8_TARGET_ARCH_MIPS
     57 #include "src/mips/lithium-codegen-mips.h"  // NOLINT
     58 #elif V8_TARGET_ARCH_MIPS64
     59 #include "src/mips64/lithium-codegen-mips64.h"  // NOLINT
     60 #elif V8_TARGET_ARCH_X87
     61 #include "src/x87/lithium-codegen-x87.h"  // NOLINT
     62 #else
     63 #error Unsupported target architecture.
     64 #endif
     65 
     66 namespace v8 {
     67 namespace internal {
     68 
     69 HBasicBlock::HBasicBlock(HGraph* graph)
     70     : block_id_(graph->GetNextBlockID()),
     71       graph_(graph),
     72       phis_(4, graph->zone()),
     73       first_(NULL),
     74       last_(NULL),
     75       end_(NULL),
     76       loop_information_(NULL),
     77       predecessors_(2, graph->zone()),
     78       dominator_(NULL),
     79       dominated_blocks_(4, graph->zone()),
     80       last_environment_(NULL),
     81       argument_count_(-1),
     82       first_instruction_index_(-1),
     83       last_instruction_index_(-1),
     84       deleted_phis_(4, graph->zone()),
     85       parent_loop_header_(NULL),
     86       inlined_entry_block_(NULL),
     87       is_inline_return_target_(false),
     88       is_reachable_(true),
     89       dominates_loop_successors_(false),
     90       is_osr_entry_(false),
     91       is_ordered_(false) { }
     92 
     93 
     94 Isolate* HBasicBlock::isolate() const {
     95   return graph_->isolate();
     96 }
     97 
     98 
     99 void HBasicBlock::MarkUnreachable() {
    100   is_reachable_ = false;
    101 }
    102 
    103 
    104 void HBasicBlock::AttachLoopInformation() {
    105   DCHECK(!IsLoopHeader());
    106   loop_information_ = new(zone()) HLoopInformation(this, zone());
    107 }
    108 
    109 
    110 void HBasicBlock::DetachLoopInformation() {
    111   DCHECK(IsLoopHeader());
    112   loop_information_ = NULL;
    113 }
    114 
    115 
    116 void HBasicBlock::AddPhi(HPhi* phi) {
    117   DCHECK(!IsStartBlock());
    118   phis_.Add(phi, zone());
    119   phi->SetBlock(this);
    120 }
    121 
    122 
    123 void HBasicBlock::RemovePhi(HPhi* phi) {
    124   DCHECK(phi->block() == this);
    125   DCHECK(phis_.Contains(phi));
    126   phi->Kill();
    127   phis_.RemoveElement(phi);
    128   phi->SetBlock(NULL);
    129 }
    130 
    131 
    132 void HBasicBlock::AddInstruction(HInstruction* instr,
    133                                  HSourcePosition position) {
    134   DCHECK(!IsStartBlock() || !IsFinished());
    135   DCHECK(!instr->IsLinked());
    136   DCHECK(!IsFinished());
    137 
    138   if (!position.IsUnknown()) {
    139     instr->set_position(position);
    140   }
    141   if (first_ == NULL) {
    142     DCHECK(last_environment() != NULL);
    143     DCHECK(!last_environment()->ast_id().IsNone());
    144     HBlockEntry* entry = new(zone()) HBlockEntry();
    145     entry->InitializeAsFirst(this);
    146     if (!position.IsUnknown()) {
    147       entry->set_position(position);
    148     } else {
    149       DCHECK(!FLAG_hydrogen_track_positions ||
    150              !graph()->info()->IsOptimizing());
    151     }
    152     first_ = last_ = entry;
    153   }
    154   instr->InsertAfter(last_);
    155 }
    156 
    157 
    158 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
    159   if (graph()->IsInsideNoSideEffectsScope()) {
    160     merged_index = HPhi::kInvalidMergedIndex;
    161   }
    162   HPhi* phi = new(zone()) HPhi(merged_index, zone());
    163   AddPhi(phi);
    164   return phi;
    165 }
    166 
    167 
    168 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
    169                                        RemovableSimulate removable) {
    170   DCHECK(HasEnvironment());
    171   HEnvironment* environment = last_environment();
    172   DCHECK(ast_id.IsNone() ||
    173          ast_id == BailoutId::StubEntry() ||
    174          environment->closure()->shared()->VerifyBailoutId(ast_id));
    175 
    176   int push_count = environment->push_count();
    177   int pop_count = environment->pop_count();
    178 
    179   HSimulate* instr =
    180       new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
    181 #ifdef DEBUG
    182   instr->set_closure(environment->closure());
    183 #endif
    184   // Order of pushed values: newest (top of stack) first. This allows
    185   // HSimulate::MergeWith() to easily append additional pushed values
    186   // that are older (from further down the stack).
    187   for (int i = 0; i < push_count; ++i) {
    188     instr->AddPushedValue(environment->ExpressionStackAt(i));
    189   }
    190   for (GrowableBitVector::Iterator it(environment->assigned_variables(),
    191                                       zone());
    192        !it.Done();
    193        it.Advance()) {
    194     int index = it.Current();
    195     instr->AddAssignedValue(index, environment->Lookup(index));
    196   }
    197   environment->ClearHistory();
    198   return instr;
    199 }
    200 
    201 
    202 void HBasicBlock::Finish(HControlInstruction* end, HSourcePosition position) {
    203   DCHECK(!IsFinished());
    204   AddInstruction(end, position);
    205   end_ = end;
    206   for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    207     it.Current()->RegisterPredecessor(this);
    208   }
    209 }
    210 
    211 
    212 void HBasicBlock::Goto(HBasicBlock* block,
    213                        HSourcePosition position,
    214                        FunctionState* state,
    215                        bool add_simulate) {
    216   bool drop_extra = state != NULL &&
    217       state->inlining_kind() == NORMAL_RETURN;
    218 
    219   if (block->IsInlineReturnTarget()) {
    220     HEnvironment* env = last_environment();
    221     int argument_count = env->arguments_environment()->parameter_count();
    222     AddInstruction(new(zone())
    223                    HLeaveInlined(state->entry(), argument_count),
    224                    position);
    225     UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
    226   }
    227 
    228   if (add_simulate) AddNewSimulate(BailoutId::None(), position);
    229   HGoto* instr = new(zone()) HGoto(block);
    230   Finish(instr, position);
    231 }
    232 
    233 
    234 void HBasicBlock::AddLeaveInlined(HValue* return_value,
    235                                   FunctionState* state,
    236                                   HSourcePosition position) {
    237   HBasicBlock* target = state->function_return();
    238   bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
    239 
    240   DCHECK(target->IsInlineReturnTarget());
    241   DCHECK(return_value != NULL);
    242   HEnvironment* env = last_environment();
    243   int argument_count = env->arguments_environment()->parameter_count();
    244   AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
    245                  position);
    246   UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
    247   last_environment()->Push(return_value);
    248   AddNewSimulate(BailoutId::None(), position);
    249   HGoto* instr = new(zone()) HGoto(target);
    250   Finish(instr, position);
    251 }
    252 
    253 
    254 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
    255   DCHECK(!HasEnvironment());
    256   DCHECK(first() == NULL);
    257   UpdateEnvironment(env);
    258 }
    259 
    260 
    261 void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
    262   last_environment_ = env;
    263   graph()->update_maximum_environment_size(env->first_expression_index());
    264 }
    265 
    266 
    267 void HBasicBlock::SetJoinId(BailoutId ast_id) {
    268   int length = predecessors_.length();
    269   DCHECK(length > 0);
    270   for (int i = 0; i < length; i++) {
    271     HBasicBlock* predecessor = predecessors_[i];
    272     DCHECK(predecessor->end()->IsGoto());
    273     HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
    274     DCHECK(i != 0 ||
    275            (predecessor->last_environment()->closure().is_null() ||
    276             predecessor->last_environment()->closure()->shared()
    277               ->VerifyBailoutId(ast_id)));
    278     simulate->set_ast_id(ast_id);
    279     predecessor->last_environment()->set_ast_id(ast_id);
    280   }
    281 }
    282 
    283 
    284 bool HBasicBlock::Dominates(HBasicBlock* other) const {
    285   HBasicBlock* current = other->dominator();
    286   while (current != NULL) {
    287     if (current == this) return true;
    288     current = current->dominator();
    289   }
    290   return false;
    291 }
    292 
    293 
    294 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
    295   if (this == other) return true;
    296   return Dominates(other);
    297 }
    298 
    299 
    300 int HBasicBlock::LoopNestingDepth() const {
    301   const HBasicBlock* current = this;
    302   int result  = (current->IsLoopHeader()) ? 1 : 0;
    303   while (current->parent_loop_header() != NULL) {
    304     current = current->parent_loop_header();
    305     result++;
    306   }
    307   return result;
    308 }
    309 
    310 
    311 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
    312   DCHECK(IsLoopHeader());
    313 
    314   SetJoinId(stmt->EntryId());
    315   if (predecessors()->length() == 1) {
    316     // This is a degenerated loop.
    317     DetachLoopInformation();
    318     return;
    319   }
    320 
    321   // Only the first entry into the loop is from outside the loop. All other
    322   // entries must be back edges.
    323   for (int i = 1; i < predecessors()->length(); ++i) {
    324     loop_information()->RegisterBackEdge(predecessors()->at(i));
    325   }
    326 }
    327 
    328 
    329 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
    330   DCHECK(IsFinished());
    331   HBasicBlock* succ_block = end()->SuccessorAt(succ);
    332 
    333   DCHECK(succ_block->predecessors()->length() == 1);
    334   succ_block->MarkUnreachable();
    335 }
    336 
    337 
    338 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
    339   if (HasPredecessor()) {
    340     // Only loop header blocks can have a predecessor added after
    341     // instructions have been added to the block (they have phis for all
    342     // values in the environment, these phis may be eliminated later).
    343     DCHECK(IsLoopHeader() || first_ == NULL);
    344     HEnvironment* incoming_env = pred->last_environment();
    345     if (IsLoopHeader()) {
    346       DCHECK(phis()->length() == incoming_env->length());
    347       for (int i = 0; i < phis_.length(); ++i) {
    348         phis_[i]->AddInput(incoming_env->values()->at(i));
    349       }
    350     } else {
    351       last_environment()->AddIncomingEdge(this, pred->last_environment());
    352     }
    353   } else if (!HasEnvironment() && !IsFinished()) {
    354     DCHECK(!IsLoopHeader());
    355     SetInitialEnvironment(pred->last_environment()->Copy());
    356   }
    357 
    358   predecessors_.Add(pred, zone());
    359 }
    360 
    361 
    362 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
    363   DCHECK(!dominated_blocks_.Contains(block));
    364   // Keep the list of dominated blocks sorted such that if there is two
    365   // succeeding block in this list, the predecessor is before the successor.
    366   int index = 0;
    367   while (index < dominated_blocks_.length() &&
    368          dominated_blocks_[index]->block_id() < block->block_id()) {
    369     ++index;
    370   }
    371   dominated_blocks_.InsertAt(index, block, zone());
    372 }
    373 
    374 
    375 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
    376   if (dominator_ == NULL) {
    377     dominator_ = other;
    378     other->AddDominatedBlock(this);
    379   } else if (other->dominator() != NULL) {
    380     HBasicBlock* first = dominator_;
    381     HBasicBlock* second = other;
    382 
    383     while (first != second) {
    384       if (first->block_id() > second->block_id()) {
    385         first = first->dominator();
    386       } else {
    387         second = second->dominator();
    388       }
    389       DCHECK(first != NULL && second != NULL);
    390     }
    391 
    392     if (dominator_ != first) {
    393       DCHECK(dominator_->dominated_blocks_.Contains(this));
    394       dominator_->dominated_blocks_.RemoveElement(this);
    395       dominator_ = first;
    396       first->AddDominatedBlock(this);
    397     }
    398   }
    399 }
    400 
    401 
    402 void HBasicBlock::AssignLoopSuccessorDominators() {
    403   // Mark blocks that dominate all subsequent reachable blocks inside their
    404   // loop. Exploit the fact that blocks are sorted in reverse post order. When
    405   // the loop is visited in increasing block id order, if the number of
    406   // non-loop-exiting successor edges at the dominator_candidate block doesn't
    407   // exceed the number of previously encountered predecessor edges, there is no
    408   // path from the loop header to any block with higher id that doesn't go
    409   // through the dominator_candidate block. In this case, the
    410   // dominator_candidate block is guaranteed to dominate all blocks reachable
    411   // from it with higher ids.
    412   HBasicBlock* last = loop_information()->GetLastBackEdge();
    413   int outstanding_successors = 1;  // one edge from the pre-header
    414   // Header always dominates everything.
    415   MarkAsLoopSuccessorDominator();
    416   for (int j = block_id(); j <= last->block_id(); ++j) {
    417     HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
    418     for (HPredecessorIterator it(dominator_candidate); !it.Done();
    419          it.Advance()) {
    420       HBasicBlock* predecessor = it.Current();
    421       // Don't count back edges.
    422       if (predecessor->block_id() < dominator_candidate->block_id()) {
    423         outstanding_successors--;
    424       }
    425     }
    426 
    427     // If more successors than predecessors have been seen in the loop up to
    428     // now, it's not possible to guarantee that the current block dominates
    429     // all of the blocks with higher IDs. In this case, assume conservatively
    430     // that those paths through loop that don't go through the current block
    431     // contain all of the loop's dependencies. Also be careful to record
    432     // dominator information about the current loop that's being processed,
    433     // and not nested loops, which will be processed when
    434     // AssignLoopSuccessorDominators gets called on their header.
    435     DCHECK(outstanding_successors >= 0);
    436     HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
    437     if (outstanding_successors == 0 &&
    438         (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
    439       dominator_candidate->MarkAsLoopSuccessorDominator();
    440     }
    441     HControlInstruction* end = dominator_candidate->end();
    442     for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    443       HBasicBlock* successor = it.Current();
    444       // Only count successors that remain inside the loop and don't loop back
    445       // to a loop header.
    446       if (successor->block_id() > dominator_candidate->block_id() &&
    447           successor->block_id() <= last->block_id()) {
    448         // Backwards edges must land on loop headers.
    449         DCHECK(successor->block_id() > dominator_candidate->block_id() ||
    450                successor->IsLoopHeader());
    451         outstanding_successors++;
    452       }
    453     }
    454   }
    455 }
    456 
    457 
    458 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
    459   for (int i = 0; i < predecessors_.length(); ++i) {
    460     if (predecessors_[i] == predecessor) return i;
    461   }
    462   UNREACHABLE();
    463   return -1;
    464 }
    465 
    466 
    467 #ifdef DEBUG
    468 void HBasicBlock::Verify() {
    469   // Check that every block is finished.
    470   DCHECK(IsFinished());
    471   DCHECK(block_id() >= 0);
    472 
    473   // Check that the incoming edges are in edge split form.
    474   if (predecessors_.length() > 1) {
    475     for (int i = 0; i < predecessors_.length(); ++i) {
    476       DCHECK(predecessors_[i]->end()->SecondSuccessor() == NULL);
    477     }
    478   }
    479 }
    480 #endif
    481 
    482 
    483 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
    484   this->back_edges_.Add(block, block->zone());
    485   AddBlock(block);
    486 }
    487 
    488 
    489 HBasicBlock* HLoopInformation::GetLastBackEdge() const {
    490   int max_id = -1;
    491   HBasicBlock* result = NULL;
    492   for (int i = 0; i < back_edges_.length(); ++i) {
    493     HBasicBlock* cur = back_edges_[i];
    494     if (cur->block_id() > max_id) {
    495       max_id = cur->block_id();
    496       result = cur;
    497     }
    498   }
    499   return result;
    500 }
    501 
    502 
    503 void HLoopInformation::AddBlock(HBasicBlock* block) {
    504   if (block == loop_header()) return;
    505   if (block->parent_loop_header() == loop_header()) return;
    506   if (block->parent_loop_header() != NULL) {
    507     AddBlock(block->parent_loop_header());
    508   } else {
    509     block->set_parent_loop_header(loop_header());
    510     blocks_.Add(block, block->zone());
    511     for (int i = 0; i < block->predecessors()->length(); ++i) {
    512       AddBlock(block->predecessors()->at(i));
    513     }
    514   }
    515 }
    516 
    517 
    518 #ifdef DEBUG
    519 
    520 // Checks reachability of the blocks in this graph and stores a bit in
    521 // the BitVector "reachable()" for every block that can be reached
    522 // from the start block of the graph. If "dont_visit" is non-null, the given
    523 // block is treated as if it would not be part of the graph. "visited_count()"
    524 // returns the number of reachable blocks.
    525 class ReachabilityAnalyzer BASE_EMBEDDED {
    526  public:
    527   ReachabilityAnalyzer(HBasicBlock* entry_block,
    528                        int block_count,
    529                        HBasicBlock* dont_visit)
    530       : visited_count_(0),
    531         stack_(16, entry_block->zone()),
    532         reachable_(block_count, entry_block->zone()),
    533         dont_visit_(dont_visit) {
    534     PushBlock(entry_block);
    535     Analyze();
    536   }
    537 
    538   int visited_count() const { return visited_count_; }
    539   const BitVector* reachable() const { return &reachable_; }
    540 
    541  private:
    542   void PushBlock(HBasicBlock* block) {
    543     if (block != NULL && block != dont_visit_ &&
    544         !reachable_.Contains(block->block_id())) {
    545       reachable_.Add(block->block_id());
    546       stack_.Add(block, block->zone());
    547       visited_count_++;
    548     }
    549   }
    550 
    551   void Analyze() {
    552     while (!stack_.is_empty()) {
    553       HControlInstruction* end = stack_.RemoveLast()->end();
    554       for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    555         PushBlock(it.Current());
    556       }
    557     }
    558   }
    559 
    560   int visited_count_;
    561   ZoneList<HBasicBlock*> stack_;
    562   BitVector reachable_;
    563   HBasicBlock* dont_visit_;
    564 };
    565 
    566 
    567 void HGraph::Verify(bool do_full_verify) const {
    568   Heap::RelocationLock relocation_lock(isolate()->heap());
    569   AllowHandleDereference allow_deref;
    570   AllowDeferredHandleDereference allow_deferred_deref;
    571   for (int i = 0; i < blocks_.length(); i++) {
    572     HBasicBlock* block = blocks_.at(i);
    573 
    574     block->Verify();
    575 
    576     // Check that every block contains at least one node and that only the last
    577     // node is a control instruction.
    578     HInstruction* current = block->first();
    579     DCHECK(current != NULL && current->IsBlockEntry());
    580     while (current != NULL) {
    581       DCHECK((current->next() == NULL) == current->IsControlInstruction());
    582       DCHECK(current->block() == block);
    583       current->Verify();
    584       current = current->next();
    585     }
    586 
    587     // Check that successors are correctly set.
    588     HBasicBlock* first = block->end()->FirstSuccessor();
    589     HBasicBlock* second = block->end()->SecondSuccessor();
    590     DCHECK(second == NULL || first != NULL);
    591 
    592     // Check that the predecessor array is correct.
    593     if (first != NULL) {
    594       DCHECK(first->predecessors()->Contains(block));
    595       if (second != NULL) {
    596         DCHECK(second->predecessors()->Contains(block));
    597       }
    598     }
    599 
    600     // Check that phis have correct arguments.
    601     for (int j = 0; j < block->phis()->length(); j++) {
    602       HPhi* phi = block->phis()->at(j);
    603       phi->Verify();
    604     }
    605 
    606     // Check that all join blocks have predecessors that end with an
    607     // unconditional goto and agree on their environment node id.
    608     if (block->predecessors()->length() >= 2) {
    609       BailoutId id =
    610           block->predecessors()->first()->last_environment()->ast_id();
    611       for (int k = 0; k < block->predecessors()->length(); k++) {
    612         HBasicBlock* predecessor = block->predecessors()->at(k);
    613         DCHECK(predecessor->end()->IsGoto() ||
    614                predecessor->end()->IsDeoptimize());
    615         DCHECK(predecessor->last_environment()->ast_id() == id);
    616       }
    617     }
    618   }
    619 
    620   // Check special property of first block to have no predecessors.
    621   DCHECK(blocks_.at(0)->predecessors()->is_empty());
    622 
    623   if (do_full_verify) {
    624     // Check that the graph is fully connected.
    625     ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
    626     DCHECK(analyzer.visited_count() == blocks_.length());
    627 
    628     // Check that entry block dominator is NULL.
    629     DCHECK(entry_block_->dominator() == NULL);
    630 
    631     // Check dominators.
    632     for (int i = 0; i < blocks_.length(); ++i) {
    633       HBasicBlock* block = blocks_.at(i);
    634       if (block->dominator() == NULL) {
    635         // Only start block may have no dominator assigned to.
    636         DCHECK(i == 0);
    637       } else {
    638         // Assert that block is unreachable if dominator must not be visited.
    639         ReachabilityAnalyzer dominator_analyzer(entry_block_,
    640                                                 blocks_.length(),
    641                                                 block->dominator());
    642         DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id()));
    643       }
    644     }
    645   }
    646 }
    647 
    648 #endif
    649 
    650 
    651 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
    652                                int32_t value) {
    653   if (!pointer->is_set()) {
    654     // Can't pass GetInvalidContext() to HConstant::New, because that will
    655     // recursively call GetConstant
    656     HConstant* constant = HConstant::New(zone(), NULL, value);
    657     constant->InsertAfter(entry_block()->first());
    658     pointer->set(constant);
    659     return constant;
    660   }
    661   return ReinsertConstantIfNecessary(pointer->get());
    662 }
    663 
    664 
    665 HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
    666   if (!constant->IsLinked()) {
    667     // The constant was removed from the graph. Reinsert.
    668     constant->ClearFlag(HValue::kIsDead);
    669     constant->InsertAfter(entry_block()->first());
    670   }
    671   return constant;
    672 }
    673 
    674 
    675 HConstant* HGraph::GetConstant0() {
    676   return GetConstant(&constant_0_, 0);
    677 }
    678 
    679 
    680 HConstant* HGraph::GetConstant1() {
    681   return GetConstant(&constant_1_, 1);
    682 }
    683 
    684 
    685 HConstant* HGraph::GetConstantMinus1() {
    686   return GetConstant(&constant_minus1_, -1);
    687 }
    688 
    689 
    690 #define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value)            \
    691 HConstant* HGraph::GetConstant##Name() {                                       \
    692   if (!constant_##name##_.is_set()) {                                          \
    693     HConstant* constant = new(zone()) HConstant(                               \
    694         Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
    695         Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()),      \
    696         false,                                                                 \
    697         Representation::Tagged(),                                              \
    698         htype,                                                                 \
    699         true,                                                                  \
    700         boolean_value,                                                         \
    701         false,                                                                 \
    702         ODDBALL_TYPE);                                                         \
    703     constant->InsertAfter(entry_block()->first());                             \
    704     constant_##name##_.set(constant);                                          \
    705   }                                                                            \
    706   return ReinsertConstantIfNecessary(constant_##name##_.get());                \
    707 }
    708 
    709 
    710 DEFINE_GET_CONSTANT(Undefined, undefined, undefined, HType::Undefined(), false)
    711 DEFINE_GET_CONSTANT(True, true, boolean, HType::Boolean(), true)
    712 DEFINE_GET_CONSTANT(False, false, boolean, HType::Boolean(), false)
    713 DEFINE_GET_CONSTANT(Hole, the_hole, the_hole, HType::None(), false)
    714 DEFINE_GET_CONSTANT(Null, null, null, HType::Null(), false)
    715 
    716 
    717 #undef DEFINE_GET_CONSTANT
    718 
    719 #define DEFINE_IS_CONSTANT(Name, name)                                         \
    720 bool HGraph::IsConstant##Name(HConstant* constant) {                           \
    721   return constant_##name##_.is_set() && constant == constant_##name##_.get();  \
    722 }
    723 DEFINE_IS_CONSTANT(Undefined, undefined)
    724 DEFINE_IS_CONSTANT(0, 0)
    725 DEFINE_IS_CONSTANT(1, 1)
    726 DEFINE_IS_CONSTANT(Minus1, minus1)
    727 DEFINE_IS_CONSTANT(True, true)
    728 DEFINE_IS_CONSTANT(False, false)
    729 DEFINE_IS_CONSTANT(Hole, the_hole)
    730 DEFINE_IS_CONSTANT(Null, null)
    731 
    732 #undef DEFINE_IS_CONSTANT
    733 
    734 
    735 HConstant* HGraph::GetInvalidContext() {
    736   return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
    737 }
    738 
    739 
    740 bool HGraph::IsStandardConstant(HConstant* constant) {
    741   if (IsConstantUndefined(constant)) return true;
    742   if (IsConstant0(constant)) return true;
    743   if (IsConstant1(constant)) return true;
    744   if (IsConstantMinus1(constant)) return true;
    745   if (IsConstantTrue(constant)) return true;
    746   if (IsConstantFalse(constant)) return true;
    747   if (IsConstantHole(constant)) return true;
    748   if (IsConstantNull(constant)) return true;
    749   return false;
    750 }
    751 
    752 
    753 HGraphBuilder::IfBuilder::IfBuilder() : builder_(NULL), needs_compare_(true) {}
    754 
    755 
    756 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
    757     : needs_compare_(true) {
    758   Initialize(builder);
    759 }
    760 
    761 
    762 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
    763                                     HIfContinuation* continuation)
    764     : needs_compare_(false), first_true_block_(NULL), first_false_block_(NULL) {
    765   InitializeDontCreateBlocks(builder);
    766   continuation->Continue(&first_true_block_, &first_false_block_);
    767 }
    768 
    769 
    770 void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
    771     HGraphBuilder* builder) {
    772   builder_ = builder;
    773   finished_ = false;
    774   did_then_ = false;
    775   did_else_ = false;
    776   did_else_if_ = false;
    777   did_and_ = false;
    778   did_or_ = false;
    779   captured_ = false;
    780   pending_merge_block_ = false;
    781   split_edge_merge_block_ = NULL;
    782   merge_at_join_blocks_ = NULL;
    783   normal_merge_at_join_block_count_ = 0;
    784   deopt_merge_at_join_block_count_ = 0;
    785 }
    786 
    787 
    788 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
    789   InitializeDontCreateBlocks(builder);
    790   HEnvironment* env = builder->environment();
    791   first_true_block_ = builder->CreateBasicBlock(env->Copy());
    792   first_false_block_ = builder->CreateBasicBlock(env->Copy());
    793 }
    794 
    795 
    796 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
    797     HControlInstruction* compare) {
    798   DCHECK(did_then_ == did_else_);
    799   if (did_else_) {
    800     // Handle if-then-elseif
    801     did_else_if_ = true;
    802     did_else_ = false;
    803     did_then_ = false;
    804     did_and_ = false;
    805     did_or_ = false;
    806     pending_merge_block_ = false;
    807     split_edge_merge_block_ = NULL;
    808     HEnvironment* env = builder()->environment();
    809     first_true_block_ = builder()->CreateBasicBlock(env->Copy());
    810     first_false_block_ = builder()->CreateBasicBlock(env->Copy());
    811   }
    812   if (split_edge_merge_block_ != NULL) {
    813     HEnvironment* env = first_false_block_->last_environment();
    814     HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
    815     if (did_or_) {
    816       compare->SetSuccessorAt(0, split_edge);
    817       compare->SetSuccessorAt(1, first_false_block_);
    818     } else {
    819       compare->SetSuccessorAt(0, first_true_block_);
    820       compare->SetSuccessorAt(1, split_edge);
    821     }
    822     builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
    823   } else {
    824     compare->SetSuccessorAt(0, first_true_block_);
    825     compare->SetSuccessorAt(1, first_false_block_);
    826   }
    827   builder()->FinishCurrentBlock(compare);
    828   needs_compare_ = false;
    829   return compare;
    830 }
    831 
    832 
    833 void HGraphBuilder::IfBuilder::Or() {
    834   DCHECK(!needs_compare_);
    835   DCHECK(!did_and_);
    836   did_or_ = true;
    837   HEnvironment* env = first_false_block_->last_environment();
    838   if (split_edge_merge_block_ == NULL) {
    839     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
    840     builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
    841     first_true_block_ = split_edge_merge_block_;
    842   }
    843   builder()->set_current_block(first_false_block_);
    844   first_false_block_ = builder()->CreateBasicBlock(env->Copy());
    845 }
    846 
    847 
    848 void HGraphBuilder::IfBuilder::And() {
    849   DCHECK(!needs_compare_);
    850   DCHECK(!did_or_);
    851   did_and_ = true;
    852   HEnvironment* env = first_false_block_->last_environment();
    853   if (split_edge_merge_block_ == NULL) {
    854     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
    855     builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
    856     first_false_block_ = split_edge_merge_block_;
    857   }
    858   builder()->set_current_block(first_true_block_);
    859   first_true_block_ = builder()->CreateBasicBlock(env->Copy());
    860 }
    861 
    862 
    863 void HGraphBuilder::IfBuilder::CaptureContinuation(
    864     HIfContinuation* continuation) {
    865   DCHECK(!did_else_if_);
    866   DCHECK(!finished_);
    867   DCHECK(!captured_);
    868 
    869   HBasicBlock* true_block = NULL;
    870   HBasicBlock* false_block = NULL;
    871   Finish(&true_block, &false_block);
    872   DCHECK(true_block != NULL);
    873   DCHECK(false_block != NULL);
    874   continuation->Capture(true_block, false_block);
    875   captured_ = true;
    876   builder()->set_current_block(NULL);
    877   End();
    878 }
    879 
    880 
    881 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
    882   DCHECK(!did_else_if_);
    883   DCHECK(!finished_);
    884   DCHECK(!captured_);
    885   HBasicBlock* true_block = NULL;
    886   HBasicBlock* false_block = NULL;
    887   Finish(&true_block, &false_block);
    888   merge_at_join_blocks_ = NULL;
    889   if (true_block != NULL && !true_block->IsFinished()) {
    890     DCHECK(continuation->IsTrueReachable());
    891     builder()->GotoNoSimulate(true_block, continuation->true_branch());
    892   }
    893   if (false_block != NULL && !false_block->IsFinished()) {
    894     DCHECK(continuation->IsFalseReachable());
    895     builder()->GotoNoSimulate(false_block, continuation->false_branch());
    896   }
    897   captured_ = true;
    898   End();
    899 }
    900 
    901 
    902 void HGraphBuilder::IfBuilder::Then() {
    903   DCHECK(!captured_);
    904   DCHECK(!finished_);
    905   did_then_ = true;
    906   if (needs_compare_) {
    907     // Handle if's without any expressions, they jump directly to the "else"
    908     // branch. However, we must pretend that the "then" branch is reachable,
    909     // so that the graph builder visits it and sees any live range extending
    910     // constructs within it.
    911     HConstant* constant_false = builder()->graph()->GetConstantFalse();
    912     ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
    913     boolean_type.Add(ToBooleanStub::BOOLEAN);
    914     HBranch* branch = builder()->New<HBranch>(
    915         constant_false, boolean_type, first_true_block_, first_false_block_);
    916     builder()->FinishCurrentBlock(branch);
    917   }
    918   builder()->set_current_block(first_true_block_);
    919   pending_merge_block_ = true;
    920 }
    921 
    922 
    923 void HGraphBuilder::IfBuilder::Else() {
    924   DCHECK(did_then_);
    925   DCHECK(!captured_);
    926   DCHECK(!finished_);
    927   AddMergeAtJoinBlock(false);
    928   builder()->set_current_block(first_false_block_);
    929   pending_merge_block_ = true;
    930   did_else_ = true;
    931 }
    932 
    933 
    934 void HGraphBuilder::IfBuilder::Deopt(const char* reason) {
    935   DCHECK(did_then_);
    936   builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
    937   AddMergeAtJoinBlock(true);
    938 }
    939 
    940 
    941 void HGraphBuilder::IfBuilder::Return(HValue* value) {
    942   HValue* parameter_count = builder()->graph()->GetConstantMinus1();
    943   builder()->FinishExitCurrentBlock(
    944       builder()->New<HReturn>(value, parameter_count));
    945   AddMergeAtJoinBlock(false);
    946 }
    947 
    948 
    949 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
    950   if (!pending_merge_block_) return;
    951   HBasicBlock* block = builder()->current_block();
    952   DCHECK(block == NULL || !block->IsFinished());
    953   MergeAtJoinBlock* record = new (builder()->zone())
    954       MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
    955   merge_at_join_blocks_ = record;
    956   if (block != NULL) {
    957     DCHECK(block->end() == NULL);
    958     if (deopt) {
    959       normal_merge_at_join_block_count_++;
    960     } else {
    961       deopt_merge_at_join_block_count_++;
    962     }
    963   }
    964   builder()->set_current_block(NULL);
    965   pending_merge_block_ = false;
    966 }
    967 
    968 
    969 void HGraphBuilder::IfBuilder::Finish() {
    970   DCHECK(!finished_);
    971   if (!did_then_) {
    972     Then();
    973   }
    974   AddMergeAtJoinBlock(false);
    975   if (!did_else_) {
    976     Else();
    977     AddMergeAtJoinBlock(false);
    978   }
    979   finished_ = true;
    980 }
    981 
    982 
    983 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
    984                                       HBasicBlock** else_continuation) {
    985   Finish();
    986 
    987   MergeAtJoinBlock* else_record = merge_at_join_blocks_;
    988   if (else_continuation != NULL) {
    989     *else_continuation = else_record->block_;
    990   }
    991   MergeAtJoinBlock* then_record = else_record->next_;
    992   if (then_continuation != NULL) {
    993     *then_continuation = then_record->block_;
    994   }
    995   DCHECK(then_record->next_ == NULL);
    996 }
    997 
    998 
    999 void HGraphBuilder::IfBuilder::End() {
   1000   if (captured_) return;
   1001   Finish();
   1002 
   1003   int total_merged_blocks = normal_merge_at_join_block_count_ +
   1004     deopt_merge_at_join_block_count_;
   1005   DCHECK(total_merged_blocks >= 1);
   1006   HBasicBlock* merge_block =
   1007       total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock();
   1008 
   1009   // Merge non-deopt blocks first to ensure environment has right size for
   1010   // padding.
   1011   MergeAtJoinBlock* current = merge_at_join_blocks_;
   1012   while (current != NULL) {
   1013     if (!current->deopt_ && current->block_ != NULL) {
   1014       // If there is only one block that makes it through to the end of the
   1015       // if, then just set it as the current block and continue rather then
   1016       // creating an unnecessary merge block.
   1017       if (total_merged_blocks == 1) {
   1018         builder()->set_current_block(current->block_);
   1019         return;
   1020       }
   1021       builder()->GotoNoSimulate(current->block_, merge_block);
   1022     }
   1023     current = current->next_;
   1024   }
   1025 
   1026   // Merge deopt blocks, padding when necessary.
   1027   current = merge_at_join_blocks_;
   1028   while (current != NULL) {
   1029     if (current->deopt_ && current->block_ != NULL) {
   1030       current->block_->FinishExit(HAbnormalExit::New(builder()->zone(), NULL),
   1031                                   HSourcePosition::Unknown());
   1032     }
   1033     current = current->next_;
   1034   }
   1035   builder()->set_current_block(merge_block);
   1036 }
   1037 
   1038 
   1039 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
   1040   Initialize(builder, NULL, kWhileTrue, NULL);
   1041 }
   1042 
   1043 
   1044 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
   1045                                         LoopBuilder::Direction direction) {
   1046   Initialize(builder, context, direction, builder->graph()->GetConstant1());
   1047 }
   1048 
   1049 
   1050 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
   1051                                         LoopBuilder::Direction direction,
   1052                                         HValue* increment_amount) {
   1053   Initialize(builder, context, direction, increment_amount);
   1054   increment_amount_ = increment_amount;
   1055 }
   1056 
   1057 
   1058 void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
   1059                                             HValue* context,
   1060                                             Direction direction,
   1061                                             HValue* increment_amount) {
   1062   builder_ = builder;
   1063   context_ = context;
   1064   direction_ = direction;
   1065   increment_amount_ = increment_amount;
   1066 
   1067   finished_ = false;
   1068   header_block_ = builder->CreateLoopHeaderBlock();
   1069   body_block_ = NULL;
   1070   exit_block_ = NULL;
   1071   exit_trampoline_block_ = NULL;
   1072 }
   1073 
   1074 
   1075 HValue* HGraphBuilder::LoopBuilder::BeginBody(
   1076     HValue* initial,
   1077     HValue* terminating,
   1078     Token::Value token) {
   1079   DCHECK(direction_ != kWhileTrue);
   1080   HEnvironment* env = builder_->environment();
   1081   phi_ = header_block_->AddNewPhi(env->values()->length());
   1082   phi_->AddInput(initial);
   1083   env->Push(initial);
   1084   builder_->GotoNoSimulate(header_block_);
   1085 
   1086   HEnvironment* body_env = env->Copy();
   1087   HEnvironment* exit_env = env->Copy();
   1088   // Remove the phi from the expression stack
   1089   body_env->Pop();
   1090   exit_env->Pop();
   1091   body_block_ = builder_->CreateBasicBlock(body_env);
   1092   exit_block_ = builder_->CreateBasicBlock(exit_env);
   1093 
   1094   builder_->set_current_block(header_block_);
   1095   env->Pop();
   1096   builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
   1097           phi_, terminating, token, body_block_, exit_block_));
   1098 
   1099   builder_->set_current_block(body_block_);
   1100   if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
   1101     HValue* one = builder_->graph()->GetConstant1();
   1102     if (direction_ == kPreIncrement) {
   1103       increment_ = HAdd::New(zone(), context_, phi_, one);
   1104     } else {
   1105       increment_ = HSub::New(zone(), context_, phi_, one);
   1106     }
   1107     increment_->ClearFlag(HValue::kCanOverflow);
   1108     builder_->AddInstruction(increment_);
   1109     return increment_;
   1110   } else {
   1111     return phi_;
   1112   }
   1113 }
   1114 
   1115 
   1116 void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) {
   1117   DCHECK(direction_ == kWhileTrue);
   1118   HEnvironment* env = builder_->environment();
   1119   builder_->GotoNoSimulate(header_block_);
   1120   builder_->set_current_block(header_block_);
   1121   env->Drop(drop_count);
   1122 }
   1123 
   1124 
   1125 void HGraphBuilder::LoopBuilder::Break() {
   1126   if (exit_trampoline_block_ == NULL) {
   1127     // Its the first time we saw a break.
   1128     if (direction_ == kWhileTrue) {
   1129       HEnvironment* env = builder_->environment()->Copy();
   1130       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
   1131     } else {
   1132       HEnvironment* env = exit_block_->last_environment()->Copy();
   1133       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
   1134       builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
   1135     }
   1136   }
   1137 
   1138   builder_->GotoNoSimulate(exit_trampoline_block_);
   1139   builder_->set_current_block(NULL);
   1140 }
   1141 
   1142 
   1143 void HGraphBuilder::LoopBuilder::EndBody() {
   1144   DCHECK(!finished_);
   1145 
   1146   if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
   1147     if (direction_ == kPostIncrement) {
   1148       increment_ = HAdd::New(zone(), context_, phi_, increment_amount_);
   1149     } else {
   1150       increment_ = HSub::New(zone(), context_, phi_, increment_amount_);
   1151     }
   1152     increment_->ClearFlag(HValue::kCanOverflow);
   1153     builder_->AddInstruction(increment_);
   1154   }
   1155 
   1156   if (direction_ != kWhileTrue) {
   1157     // Push the new increment value on the expression stack to merge into
   1158     // the phi.
   1159     builder_->environment()->Push(increment_);
   1160   }
   1161   HBasicBlock* last_block = builder_->current_block();
   1162   builder_->GotoNoSimulate(last_block, header_block_);
   1163   header_block_->loop_information()->RegisterBackEdge(last_block);
   1164 
   1165   if (exit_trampoline_block_ != NULL) {
   1166     builder_->set_current_block(exit_trampoline_block_);
   1167   } else {
   1168     builder_->set_current_block(exit_block_);
   1169   }
   1170   finished_ = true;
   1171 }
   1172 
   1173 
   1174 HGraph* HGraphBuilder::CreateGraph() {
   1175   graph_ = new(zone()) HGraph(info_);
   1176   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
   1177   CompilationPhase phase("H_Block building", info_);
   1178   set_current_block(graph()->entry_block());
   1179   if (!BuildGraph()) return NULL;
   1180   graph()->FinalizeUniqueness();
   1181   return graph_;
   1182 }
   1183 
   1184 
   1185 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
   1186   DCHECK(current_block() != NULL);
   1187   DCHECK(!FLAG_hydrogen_track_positions ||
   1188          !position_.IsUnknown() ||
   1189          !info_->IsOptimizing());
   1190   current_block()->AddInstruction(instr, source_position());
   1191   if (graph()->IsInsideNoSideEffectsScope()) {
   1192     instr->SetFlag(HValue::kHasNoObservableSideEffects);
   1193   }
   1194   return instr;
   1195 }
   1196 
   1197 
   1198 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
   1199   DCHECK(!FLAG_hydrogen_track_positions ||
   1200          !info_->IsOptimizing() ||
   1201          !position_.IsUnknown());
   1202   current_block()->Finish(last, source_position());
   1203   if (last->IsReturn() || last->IsAbnormalExit()) {
   1204     set_current_block(NULL);
   1205   }
   1206 }
   1207 
   1208 
   1209 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
   1210   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
   1211          !position_.IsUnknown());
   1212   current_block()->FinishExit(instruction, source_position());
   1213   if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
   1214     set_current_block(NULL);
   1215   }
   1216 }
   1217 
   1218 
   1219 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
   1220   if (FLAG_native_code_counters && counter->Enabled()) {
   1221     HValue* reference = Add<HConstant>(ExternalReference(counter));
   1222     HValue* old_value = Add<HLoadNamedField>(
   1223         reference, static_cast<HValue*>(NULL), HObjectAccess::ForCounter());
   1224     HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
   1225     new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
   1226     Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
   1227                           new_value, STORE_TO_INITIALIZED_ENTRY);
   1228   }
   1229 }
   1230 
   1231 
   1232 void HGraphBuilder::AddSimulate(BailoutId id,
   1233                                 RemovableSimulate removable) {
   1234   DCHECK(current_block() != NULL);
   1235   DCHECK(!graph()->IsInsideNoSideEffectsScope());
   1236   current_block()->AddNewSimulate(id, source_position(), removable);
   1237 }
   1238 
   1239 
   1240 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
   1241   HBasicBlock* b = graph()->CreateBasicBlock();
   1242   b->SetInitialEnvironment(env);
   1243   return b;
   1244 }
   1245 
   1246 
   1247 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
   1248   HBasicBlock* header = graph()->CreateBasicBlock();
   1249   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
   1250   header->SetInitialEnvironment(entry_env);
   1251   header->AttachLoopInformation();
   1252   return header;
   1253 }
   1254 
   1255 
   1256 HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) {
   1257   HValue* map = Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
   1258                                      HObjectAccess::ForMap());
   1259 
   1260   HValue* bit_field2 = Add<HLoadNamedField>(map, static_cast<HValue*>(NULL),
   1261                                             HObjectAccess::ForMapBitField2());
   1262   return BuildDecodeField<Map::ElementsKindBits>(bit_field2);
   1263 }
   1264 
   1265 
   1266 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
   1267   if (obj->type().IsHeapObject()) return obj;
   1268   return Add<HCheckHeapObject>(obj);
   1269 }
   1270 
   1271 
   1272 void HGraphBuilder::FinishExitWithHardDeoptimization(const char* reason) {
   1273   Add<HDeoptimize>(reason, Deoptimizer::EAGER);
   1274   FinishExitCurrentBlock(New<HAbnormalExit>());
   1275 }
   1276 
   1277 
   1278 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
   1279   if (!string->type().IsString()) {
   1280     DCHECK(!string->IsConstant() ||
   1281            !HConstant::cast(string)->HasStringValue());
   1282     BuildCheckHeapObject(string);
   1283     return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
   1284   }
   1285   return string;
   1286 }
   1287 
   1288 
   1289 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
   1290   if (object->type().IsJSObject()) return object;
   1291   if (function->IsConstant() &&
   1292       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   1293     Handle<JSFunction> f = Handle<JSFunction>::cast(
   1294         HConstant::cast(function)->handle(isolate()));
   1295     SharedFunctionInfo* shared = f->shared();
   1296     if (shared->strict_mode() == STRICT || shared->native()) return object;
   1297   }
   1298   return Add<HWrapReceiver>(object, function);
   1299 }
   1300 
   1301 
   1302 HValue* HGraphBuilder::BuildCheckForCapacityGrow(
   1303     HValue* object,
   1304     HValue* elements,
   1305     ElementsKind kind,
   1306     HValue* length,
   1307     HValue* key,
   1308     bool is_js_array,
   1309     PropertyAccessType access_type) {
   1310   IfBuilder length_checker(this);
   1311 
   1312   Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
   1313   length_checker.If<HCompareNumericAndBranch>(key, length, token);
   1314 
   1315   length_checker.Then();
   1316 
   1317   HValue* current_capacity = AddLoadFixedArrayLength(elements);
   1318 
   1319   IfBuilder capacity_checker(this);
   1320 
   1321   capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
   1322                                                 Token::GTE);
   1323   capacity_checker.Then();
   1324 
   1325   HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
   1326   HValue* max_capacity = AddUncasted<HAdd>(current_capacity, max_gap);
   1327 
   1328   Add<HBoundsCheck>(key, max_capacity);
   1329 
   1330   HValue* new_capacity = BuildNewElementsCapacity(key);
   1331   HValue* new_elements = BuildGrowElementsCapacity(object, elements,
   1332                                                    kind, kind, length,
   1333                                                    new_capacity);
   1334 
   1335   environment()->Push(new_elements);
   1336   capacity_checker.Else();
   1337 
   1338   environment()->Push(elements);
   1339   capacity_checker.End();
   1340 
   1341   if (is_js_array) {
   1342     HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
   1343     new_length->ClearFlag(HValue::kCanOverflow);
   1344 
   1345     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
   1346                           new_length);
   1347   }
   1348 
   1349   if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
   1350     HValue* checked_elements = environment()->Top();
   1351 
   1352     // Write zero to ensure that the new element is initialized with some smi.
   1353     Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), kind);
   1354   }
   1355 
   1356   length_checker.Else();
   1357   Add<HBoundsCheck>(key, length);
   1358 
   1359   environment()->Push(elements);
   1360   length_checker.End();
   1361 
   1362   return environment()->Pop();
   1363 }
   1364 
   1365 
   1366 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
   1367                                                 HValue* elements,
   1368                                                 ElementsKind kind,
   1369                                                 HValue* length) {
   1370   Factory* factory = isolate()->factory();
   1371 
   1372   IfBuilder cow_checker(this);
   1373 
   1374   cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
   1375   cow_checker.Then();
   1376 
   1377   HValue* capacity = AddLoadFixedArrayLength(elements);
   1378 
   1379   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
   1380                                                    kind, length, capacity);
   1381 
   1382   environment()->Push(new_elements);
   1383 
   1384   cow_checker.Else();
   1385 
   1386   environment()->Push(elements);
   1387 
   1388   cow_checker.End();
   1389 
   1390   return environment()->Pop();
   1391 }
   1392 
   1393 
   1394 void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
   1395                                                 HValue* map,
   1396                                                 ElementsKind from_kind,
   1397                                                 ElementsKind to_kind,
   1398                                                 bool is_jsarray) {
   1399   DCHECK(!IsFastHoleyElementsKind(from_kind) ||
   1400          IsFastHoleyElementsKind(to_kind));
   1401 
   1402   if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
   1403     Add<HTrapAllocationMemento>(object);
   1404   }
   1405 
   1406   if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
   1407     HInstruction* elements = AddLoadElements(object);
   1408 
   1409     HInstruction* empty_fixed_array = Add<HConstant>(
   1410         isolate()->factory()->empty_fixed_array());
   1411 
   1412     IfBuilder if_builder(this);
   1413 
   1414     if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);
   1415 
   1416     if_builder.Then();
   1417 
   1418     HInstruction* elements_length = AddLoadFixedArrayLength(elements);
   1419 
   1420     HInstruction* array_length = is_jsarray
   1421         ? Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
   1422                                HObjectAccess::ForArrayLength(from_kind))
   1423         : elements_length;
   1424 
   1425     BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
   1426                               array_length, elements_length);
   1427 
   1428     if_builder.End();
   1429   }
   1430 
   1431   Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
   1432 }
   1433 
   1434 
   1435 void HGraphBuilder::BuildJSObjectCheck(HValue* receiver,
   1436                                        int bit_field_mask) {
   1437   // Check that the object isn't a smi.
   1438   Add<HCheckHeapObject>(receiver);
   1439 
   1440   // Get the map of the receiver.
   1441   HValue* map = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL),
   1442                                      HObjectAccess::ForMap());
   1443 
   1444   // Check the instance type and if an access check is needed, this can be
   1445   // done with a single load, since both bytes are adjacent in the map.
   1446   HObjectAccess access(HObjectAccess::ForMapInstanceTypeAndBitField());
   1447   HValue* instance_type_and_bit_field =
   1448       Add<HLoadNamedField>(map, static_cast<HValue*>(NULL), access);
   1449 
   1450   HValue* mask = Add<HConstant>(0x00FF | (bit_field_mask << 8));
   1451   HValue* and_result = AddUncasted<HBitwise>(Token::BIT_AND,
   1452                                              instance_type_and_bit_field,
   1453                                              mask);
   1454   HValue* sub_result = AddUncasted<HSub>(and_result,
   1455                                          Add<HConstant>(JS_OBJECT_TYPE));
   1456   Add<HBoundsCheck>(sub_result,
   1457                     Add<HConstant>(LAST_JS_OBJECT_TYPE + 1 - JS_OBJECT_TYPE));
   1458 }
   1459 
   1460 
   1461 void HGraphBuilder::BuildKeyedIndexCheck(HValue* key,
   1462                                          HIfContinuation* join_continuation) {
   1463   // The sometimes unintuitively backward ordering of the ifs below is
   1464   // convoluted, but necessary.  All of the paths must guarantee that the
   1465   // if-true of the continuation returns a smi element index and the if-false of
   1466   // the continuation returns either a symbol or a unique string key. All other
   1467   // object types cause a deopt to fall back to the runtime.
   1468 
   1469   IfBuilder key_smi_if(this);
   1470   key_smi_if.If<HIsSmiAndBranch>(key);
   1471   key_smi_if.Then();
   1472   {
   1473     Push(key);  // Nothing to do, just continue to true of continuation.
   1474   }
   1475   key_smi_if.Else();
   1476   {
   1477     HValue* map = Add<HLoadNamedField>(key, static_cast<HValue*>(NULL),
   1478                                        HObjectAccess::ForMap());
   1479     HValue* instance_type =
   1480         Add<HLoadNamedField>(map, static_cast<HValue*>(NULL),
   1481                              HObjectAccess::ForMapInstanceType());
   1482 
   1483     // Non-unique string, check for a string with a hash code that is actually
   1484     // an index.
   1485     STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
   1486     IfBuilder not_string_or_name_if(this);
   1487     not_string_or_name_if.If<HCompareNumericAndBranch>(
   1488         instance_type,
   1489         Add<HConstant>(LAST_UNIQUE_NAME_TYPE),
   1490         Token::GT);
   1491 
   1492     not_string_or_name_if.Then();
   1493     {
   1494       // Non-smi, non-Name, non-String: Try to convert to smi in case of
   1495       // HeapNumber.
   1496       // TODO(danno): This could call some variant of ToString
   1497       Push(AddUncasted<HForceRepresentation>(key, Representation::Smi()));
   1498     }
   1499     not_string_or_name_if.Else();
   1500     {
   1501       // String or Name: check explicitly for Name, they can short-circuit
   1502       // directly to unique non-index key path.
   1503       IfBuilder not_symbol_if(this);
   1504       not_symbol_if.If<HCompareNumericAndBranch>(
   1505           instance_type,
   1506           Add<HConstant>(SYMBOL_TYPE),
   1507           Token::NE);
   1508 
   1509       not_symbol_if.Then();
   1510       {
   1511         // String: check whether the String is a String of an index. If it is,
   1512         // extract the index value from the hash.
   1513         HValue* hash =
   1514             Add<HLoadNamedField>(key, static_cast<HValue*>(NULL),
   1515                                  HObjectAccess::ForNameHashField());
   1516         HValue* not_index_mask = Add<HConstant>(static_cast<int>(
   1517             String::kContainsCachedArrayIndexMask));
   1518 
   1519         HValue* not_index_test = AddUncasted<HBitwise>(
   1520             Token::BIT_AND, hash, not_index_mask);
   1521 
   1522         IfBuilder string_index_if(this);
   1523         string_index_if.If<HCompareNumericAndBranch>(not_index_test,
   1524                                                      graph()->GetConstant0(),
   1525                                                      Token::EQ);
   1526         string_index_if.Then();
   1527         {
   1528           // String with index in hash: extract string and merge to index path.
   1529           Push(BuildDecodeField<String::ArrayIndexValueBits>(hash));
   1530         }
   1531         string_index_if.Else();
   1532         {
   1533           // Key is a non-index String, check for uniqueness/internalization.
   1534           // If it's not internalized yet, internalize it now.
   1535           HValue* not_internalized_bit = AddUncasted<HBitwise>(
   1536               Token::BIT_AND,
   1537               instance_type,
   1538               Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
   1539 
   1540           IfBuilder internalized(this);
   1541           internalized.If<HCompareNumericAndBranch>(not_internalized_bit,
   1542                                                     graph()->GetConstant0(),
   1543                                                     Token::EQ);
   1544           internalized.Then();
   1545           Push(key);
   1546 
   1547           internalized.Else();
   1548           Add<HPushArguments>(key);
   1549           HValue* intern_key = Add<HCallRuntime>(
   1550               isolate()->factory()->empty_string(),
   1551               Runtime::FunctionForId(Runtime::kInternalizeString), 1);
   1552           Push(intern_key);
   1553 
   1554           internalized.End();
   1555           // Key guaranteed to be a unique string
   1556         }
   1557         string_index_if.JoinContinuation(join_continuation);
   1558       }
   1559       not_symbol_if.Else();
   1560       {
   1561         Push(key);  // Key is symbol
   1562       }
   1563       not_symbol_if.JoinContinuation(join_continuation);
   1564     }
   1565     not_string_or_name_if.JoinContinuation(join_continuation);
   1566   }
   1567   key_smi_if.JoinContinuation(join_continuation);
   1568 }
   1569 
   1570 
   1571 void HGraphBuilder::BuildNonGlobalObjectCheck(HValue* receiver) {
   1572   // Get the the instance type of the receiver, and make sure that it is
   1573   // not one of the global object types.
   1574   HValue* map = Add<HLoadNamedField>(receiver, static_cast<HValue*>(NULL),
   1575                                      HObjectAccess::ForMap());
   1576   HValue* instance_type =
   1577     Add<HLoadNamedField>(map, static_cast<HValue*>(NULL),
   1578                          HObjectAccess::ForMapInstanceType());
   1579   STATIC_ASSERT(JS_BUILTINS_OBJECT_TYPE == JS_GLOBAL_OBJECT_TYPE + 1);
   1580   HValue* min_global_type = Add<HConstant>(JS_GLOBAL_OBJECT_TYPE);
   1581   HValue* max_global_type = Add<HConstant>(JS_BUILTINS_OBJECT_TYPE);
   1582 
   1583   IfBuilder if_global_object(this);
   1584   if_global_object.If<HCompareNumericAndBranch>(instance_type,
   1585                                                 max_global_type,
   1586                                                 Token::LTE);
   1587   if_global_object.And();
   1588   if_global_object.If<HCompareNumericAndBranch>(instance_type,
   1589                                                 min_global_type,
   1590                                                 Token::GTE);
   1591   if_global_object.ThenDeopt("receiver was a global object");
   1592   if_global_object.End();
   1593 }
   1594 
   1595 
   1596 void HGraphBuilder::BuildTestForDictionaryProperties(
   1597     HValue* object,
   1598     HIfContinuation* continuation) {
   1599   HValue* properties = Add<HLoadNamedField>(
   1600       object, static_cast<HValue*>(NULL),
   1601       HObjectAccess::ForPropertiesPointer());
   1602   HValue* properties_map =
   1603       Add<HLoadNamedField>(properties, static_cast<HValue*>(NULL),
   1604                            HObjectAccess::ForMap());
   1605   HValue* hash_map = Add<HLoadRoot>(Heap::kHashTableMapRootIndex);
   1606   IfBuilder builder(this);
   1607   builder.If<HCompareObjectEqAndBranch>(properties_map, hash_map);
   1608   builder.CaptureContinuation(continuation);
   1609 }
   1610 
   1611 
   1612 HValue* HGraphBuilder::BuildKeyedLookupCacheHash(HValue* object,
   1613                                                  HValue* key) {
   1614   // Load the map of the receiver, compute the keyed lookup cache hash
   1615   // based on 32 bits of the map pointer and the string hash.
   1616   HValue* object_map =
   1617       Add<HLoadNamedField>(object, static_cast<HValue*>(NULL),
   1618                            HObjectAccess::ForMapAsInteger32());
   1619   HValue* shifted_map = AddUncasted<HShr>(
   1620       object_map, Add<HConstant>(KeyedLookupCache::kMapHashShift));
   1621   HValue* string_hash =
   1622       Add<HLoadNamedField>(key, static_cast<HValue*>(NULL),
   1623                            HObjectAccess::ForStringHashField());
   1624   HValue* shifted_hash = AddUncasted<HShr>(
   1625       string_hash, Add<HConstant>(String::kHashShift));
   1626   HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map,
   1627                                              shifted_hash);
   1628   int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
   1629   return AddUncasted<HBitwise>(Token::BIT_AND, xor_result,
   1630                                Add<HConstant>(mask));
   1631 }
   1632 
   1633 
   1634 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
   1635   int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
   1636   HValue* seed = Add<HConstant>(seed_value);
   1637   HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);
   1638 
   1639   // hash = ~hash + (hash << 15);
   1640   HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
   1641   HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
   1642                                            graph()->GetConstantMinus1());
   1643   hash = AddUncasted<HAdd>(shifted_hash, not_hash);
   1644 
   1645   // hash = hash ^ (hash >> 12);
   1646   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
   1647   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1648 
   1649   // hash = hash + (hash << 2);
   1650   shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
   1651   hash = AddUncasted<HAdd>(hash, shifted_hash);
   1652 
   1653   // hash = hash ^ (hash >> 4);
   1654   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
   1655   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1656 
   1657   // hash = hash * 2057;
   1658   hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
   1659   hash->ClearFlag(HValue::kCanOverflow);
   1660 
   1661   // hash = hash ^ (hash >> 16);
   1662   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
   1663   return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1664 }
   1665 
   1666 
   1667 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
   1668                                                            HValue* elements,
   1669                                                            HValue* key,
   1670                                                            HValue* hash) {
   1671   HValue* capacity = Add<HLoadKeyed>(
   1672       elements,
   1673       Add<HConstant>(NameDictionary::kCapacityIndex),
   1674       static_cast<HValue*>(NULL),
   1675       FAST_ELEMENTS);
   1676 
   1677   HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
   1678   mask->ChangeRepresentation(Representation::Integer32());
   1679   mask->ClearFlag(HValue::kCanOverflow);
   1680 
   1681   HValue* entry = hash;
   1682   HValue* count = graph()->GetConstant1();
   1683   Push(entry);
   1684   Push(count);
   1685 
   1686   HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
   1687                                               graph()->CreateBasicBlock());
   1688   HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
   1689                                                graph()->CreateBasicBlock());
   1690   LoopBuilder probe_loop(this);
   1691   probe_loop.BeginBody(2);  // Drop entry, count from last environment to
   1692                             // appease live range building without simulates.
   1693 
   1694   count = Pop();
   1695   entry = Pop();
   1696   entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
   1697   int entry_size = SeededNumberDictionary::kEntrySize;
   1698   HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size));
   1699   base_index->ClearFlag(HValue::kCanOverflow);
   1700   int start_offset = SeededNumberDictionary::kElementsStartIndex;
   1701   HValue* key_index =
   1702       AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
   1703   key_index->ClearFlag(HValue::kCanOverflow);
   1704 
   1705   HValue* candidate_key = Add<HLoadKeyed>(
   1706       elements, key_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
   1707   IfBuilder if_undefined(this);
   1708   if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
   1709                                              graph()->GetConstantUndefined());
   1710   if_undefined.Then();
   1711   {
   1712     // element == undefined means "not found". Call the runtime.
   1713     // TODO(jkummerow): walk the prototype chain instead.
   1714     Add<HPushArguments>(receiver, key);
   1715     Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
   1716                            Runtime::FunctionForId(Runtime::kKeyedGetProperty),
   1717                            2));
   1718   }
   1719   if_undefined.Else();
   1720   {
   1721     IfBuilder if_match(this);
   1722     if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
   1723     if_match.Then();
   1724     if_match.Else();
   1725 
   1726     // Update non-internalized string in the dictionary with internalized key?
   1727     IfBuilder if_update_with_internalized(this);
   1728     HValue* smi_check =
   1729         if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
   1730     if_update_with_internalized.And();
   1731     HValue* map = AddLoadMap(candidate_key, smi_check);
   1732     HValue* instance_type = Add<HLoadNamedField>(
   1733         map, static_cast<HValue*>(NULL), HObjectAccess::ForMapInstanceType());
   1734     HValue* not_internalized_bit = AddUncasted<HBitwise>(
   1735         Token::BIT_AND, instance_type,
   1736         Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
   1737     if_update_with_internalized.If<HCompareNumericAndBranch>(
   1738         not_internalized_bit, graph()->GetConstant0(), Token::NE);
   1739     if_update_with_internalized.And();
   1740     if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
   1741         candidate_key, graph()->GetConstantHole());
   1742     if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
   1743                                                                key, Token::EQ);
   1744     if_update_with_internalized.Then();
   1745     // Replace a key that is a non-internalized string by the equivalent
   1746     // internalized string for faster further lookups.
   1747     Add<HStoreKeyed>(elements, key_index, key, FAST_ELEMENTS);
   1748     if_update_with_internalized.Else();
   1749 
   1750     if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
   1751     if_match.JoinContinuation(&found_key_match_continuation);
   1752 
   1753     IfBuilder found_key_match(this, &found_key_match_continuation);
   1754     found_key_match.Then();
   1755     // Key at current probe matches. Relevant bits in the |details| field must
   1756     // be zero, otherwise the dictionary element requires special handling.
   1757     HValue* details_index =
   1758         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
   1759     details_index->ClearFlag(HValue::kCanOverflow);
   1760     HValue* details = Add<HLoadKeyed>(
   1761         elements, details_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
   1762     int details_mask = PropertyDetails::TypeField::kMask |
   1763                        PropertyDetails::DeletedField::kMask;
   1764     details = AddUncasted<HBitwise>(Token::BIT_AND, details,
   1765                                     Add<HConstant>(details_mask));
   1766     IfBuilder details_compare(this);
   1767     details_compare.If<HCompareNumericAndBranch>(
   1768         details, graph()->GetConstant0(), Token::EQ);
   1769     details_compare.Then();
   1770     HValue* result_index =
   1771         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
   1772     result_index->ClearFlag(HValue::kCanOverflow);
   1773     Push(Add<HLoadKeyed>(elements, result_index, static_cast<HValue*>(NULL),
   1774                          FAST_ELEMENTS));
   1775     details_compare.Else();
   1776     Add<HPushArguments>(receiver, key);
   1777     Push(Add<HCallRuntime>(isolate()->factory()->empty_string(),
   1778                            Runtime::FunctionForId(Runtime::kKeyedGetProperty),
   1779                            2));
   1780     details_compare.End();
   1781 
   1782     found_key_match.Else();
   1783     found_key_match.JoinContinuation(&return_or_loop_continuation);
   1784   }
   1785   if_undefined.JoinContinuation(&return_or_loop_continuation);
   1786 
   1787   IfBuilder return_or_loop(this, &return_or_loop_continuation);
   1788   return_or_loop.Then();
   1789   probe_loop.Break();
   1790 
   1791   return_or_loop.Else();
   1792   entry = AddUncasted<HAdd>(entry, count);
   1793   entry->ClearFlag(HValue::kCanOverflow);
   1794   count = AddUncasted<HAdd>(count, graph()->GetConstant1());
   1795   count->ClearFlag(HValue::kCanOverflow);
   1796   Push(entry);
   1797   Push(count);
   1798 
   1799   probe_loop.EndBody();
   1800 
   1801   return_or_loop.End();
   1802 
   1803   return Pop();
   1804 }
   1805 
   1806 
   1807 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
   1808                                                   HValue* index,
   1809                                                   HValue* input) {
   1810   NoObservableSideEffectsScope scope(this);
   1811   HConstant* max_length = Add<HConstant>(JSObject::kInitialMaxFastElementArray);
   1812   Add<HBoundsCheck>(length, max_length);
   1813 
   1814   // Generate size calculation code here in order to make it dominate
   1815   // the JSRegExpResult allocation.
   1816   ElementsKind elements_kind = FAST_ELEMENTS;
   1817   HValue* size = BuildCalculateElementsSize(elements_kind, length);
   1818 
   1819   // Allocate the JSRegExpResult and the FixedArray in one step.
   1820   HValue* result = Add<HAllocate>(
   1821       Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
   1822       NOT_TENURED, JS_ARRAY_TYPE);
   1823 
   1824   // Initialize the JSRegExpResult header.
   1825   HValue* global_object = Add<HLoadNamedField>(
   1826       context(), static_cast<HValue*>(NULL),
   1827       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
   1828   HValue* native_context = Add<HLoadNamedField>(
   1829       global_object, static_cast<HValue*>(NULL),
   1830       HObjectAccess::ForGlobalObjectNativeContext());
   1831   Add<HStoreNamedField>(
   1832       result, HObjectAccess::ForMap(),
   1833       Add<HLoadNamedField>(
   1834           native_context, static_cast<HValue*>(NULL),
   1835           HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX)));
   1836   HConstant* empty_fixed_array =
   1837       Add<HConstant>(isolate()->factory()->empty_fixed_array());
   1838   Add<HStoreNamedField>(
   1839       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
   1840       empty_fixed_array);
   1841   Add<HStoreNamedField>(
   1842       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
   1843       empty_fixed_array);
   1844   Add<HStoreNamedField>(
   1845       result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length);
   1846 
   1847   // Initialize the additional fields.
   1848   Add<HStoreNamedField>(
   1849       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset),
   1850       index);
   1851   Add<HStoreNamedField>(
   1852       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset),
   1853       input);
   1854 
   1855   // Allocate and initialize the elements header.
   1856   HAllocate* elements = BuildAllocateElements(elements_kind, size);
   1857   BuildInitializeElementsHeader(elements, elements_kind, length);
   1858 
   1859   if (!elements->has_size_upper_bound()) {
   1860     HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize(
   1861         elements_kind, max_length->Integer32Value());
   1862     elements->set_size_upper_bound(size_in_bytes_upper_bound);
   1863   }
   1864 
   1865   Add<HStoreNamedField>(
   1866       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
   1867       elements);
   1868 
   1869   // Initialize the elements contents with undefined.
   1870   BuildFillElementsWithValue(
   1871       elements, elements_kind, graph()->GetConstant0(), length,
   1872       graph()->GetConstantUndefined());
   1873 
   1874   return result;
   1875 }
   1876 
   1877 
   1878 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
   1879   NoObservableSideEffectsScope scope(this);
   1880 
   1881   // Convert constant numbers at compile time.
   1882   if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
   1883     Handle<Object> number = HConstant::cast(object)->handle(isolate());
   1884     Handle<String> result = isolate()->factory()->NumberToString(number);
   1885     return Add<HConstant>(result);
   1886   }
   1887 
   1888   // Create a joinable continuation.
   1889   HIfContinuation found(graph()->CreateBasicBlock(),
   1890                         graph()->CreateBasicBlock());
   1891 
   1892   // Load the number string cache.
   1893   HValue* number_string_cache =
   1894       Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
   1895 
   1896   // Make the hash mask from the length of the number string cache. It
   1897   // contains two elements (number and string) for each cache entry.
   1898   HValue* mask = AddLoadFixedArrayLength(number_string_cache);
   1899   mask->set_type(HType::Smi());
   1900   mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
   1901   mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
   1902 
   1903   // Check whether object is a smi.
   1904   IfBuilder if_objectissmi(this);
   1905   if_objectissmi.If<HIsSmiAndBranch>(object);
   1906   if_objectissmi.Then();
   1907   {
   1908     // Compute hash for smi similar to smi_get_hash().
   1909     HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);
   1910 
   1911     // Load the key.
   1912     HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
   1913     HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
   1914                                   static_cast<HValue*>(NULL),
   1915                                   FAST_ELEMENTS, ALLOW_RETURN_HOLE);
   1916 
   1917     // Check if object == key.
   1918     IfBuilder if_objectiskey(this);
   1919     if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
   1920     if_objectiskey.Then();
   1921     {
   1922       // Make the key_index available.
   1923       Push(key_index);
   1924     }
   1925     if_objectiskey.JoinContinuation(&found);
   1926   }
   1927   if_objectissmi.Else();
   1928   {
   1929     if (type->Is(Type::SignedSmall())) {
   1930       if_objectissmi.Deopt("Expected smi");
   1931     } else {
   1932       // Check if the object is a heap number.
   1933       IfBuilder if_objectisnumber(this);
   1934       HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
   1935           object, isolate()->factory()->heap_number_map());
   1936       if_objectisnumber.Then();
   1937       {
   1938         // Compute hash for heap number similar to double_get_hash().
   1939         HValue* low = Add<HLoadNamedField>(
   1940             object, objectisnumber,
   1941             HObjectAccess::ForHeapNumberValueLowestBits());
   1942         HValue* high = Add<HLoadNamedField>(
   1943             object, objectisnumber,
   1944             HObjectAccess::ForHeapNumberValueHighestBits());
   1945         HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
   1946         hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
   1947 
   1948         // Load the key.
   1949         HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
   1950         HValue* key = Add<HLoadKeyed>(number_string_cache, key_index,
   1951                                       static_cast<HValue*>(NULL),
   1952                                       FAST_ELEMENTS, ALLOW_RETURN_HOLE);
   1953 
   1954         // Check if the key is a heap number and compare it with the object.
   1955         IfBuilder if_keyisnotsmi(this);
   1956         HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
   1957         if_keyisnotsmi.Then();
   1958         {
   1959           IfBuilder if_keyisheapnumber(this);
   1960           if_keyisheapnumber.If<HCompareMap>(
   1961               key, isolate()->factory()->heap_number_map());
   1962           if_keyisheapnumber.Then();
   1963           {
   1964             // Check if values of key and object match.
   1965             IfBuilder if_keyeqobject(this);
   1966             if_keyeqobject.If<HCompareNumericAndBranch>(
   1967                 Add<HLoadNamedField>(key, keyisnotsmi,
   1968                                      HObjectAccess::ForHeapNumberValue()),
   1969                 Add<HLoadNamedField>(object, objectisnumber,
   1970                                      HObjectAccess::ForHeapNumberValue()),
   1971                 Token::EQ);
   1972             if_keyeqobject.Then();
   1973             {
   1974               // Make the key_index available.
   1975               Push(key_index);
   1976             }
   1977             if_keyeqobject.JoinContinuation(&found);
   1978           }
   1979           if_keyisheapnumber.JoinContinuation(&found);
   1980         }
   1981         if_keyisnotsmi.JoinContinuation(&found);
   1982       }
   1983       if_objectisnumber.Else();
   1984       {
   1985         if (type->Is(Type::Number())) {
   1986           if_objectisnumber.Deopt("Expected heap number");
   1987         }
   1988       }
   1989       if_objectisnumber.JoinContinuation(&found);
   1990     }
   1991   }
   1992   if_objectissmi.JoinContinuation(&found);
   1993 
   1994   // Check for cache hit.
   1995   IfBuilder if_found(this, &found);
   1996   if_found.Then();
   1997   {
   1998     // Count number to string operation in native code.
   1999     AddIncrementCounter(isolate()->counters()->number_to_string_native());
   2000 
   2001     // Load the value in case of cache hit.
   2002     HValue* key_index = Pop();
   2003     HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
   2004     Push(Add<HLoadKeyed>(number_string_cache, value_index,
   2005                          static_cast<HValue*>(NULL),
   2006                          FAST_ELEMENTS, ALLOW_RETURN_HOLE));
   2007   }
   2008   if_found.Else();
   2009   {
   2010     // Cache miss, fallback to runtime.
   2011     Add<HPushArguments>(object);
   2012     Push(Add<HCallRuntime>(
   2013             isolate()->factory()->empty_string(),
   2014             Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
   2015             1));
   2016   }
   2017   if_found.End();
   2018 
   2019   return Pop();
   2020 }
   2021 
   2022 
   2023 HAllocate* HGraphBuilder::BuildAllocate(
   2024     HValue* object_size,
   2025     HType type,
   2026     InstanceType instance_type,
   2027     HAllocationMode allocation_mode) {
   2028   // Compute the effective allocation size.
   2029   HValue* size = object_size;
   2030   if (allocation_mode.CreateAllocationMementos()) {
   2031     size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
   2032     size->ClearFlag(HValue::kCanOverflow);
   2033   }
   2034 
   2035   // Perform the actual allocation.
   2036   HAllocate* object = Add<HAllocate>(
   2037       size, type, allocation_mode.GetPretenureMode(),
   2038       instance_type, allocation_mode.feedback_site());
   2039 
   2040   // Setup the allocation memento.
   2041   if (allocation_mode.CreateAllocationMementos()) {
   2042     BuildCreateAllocationMemento(
   2043         object, object_size, allocation_mode.current_site());
   2044   }
   2045 
   2046   return object;
   2047 }
   2048 
   2049 
   2050 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
   2051                                              HValue* right_length) {
   2052   // Compute the combined string length and check against max string length.
   2053   HValue* length = AddUncasted<HAdd>(left_length, right_length);
   2054   // Check that length <= kMaxLength <=> length < MaxLength + 1.
   2055   HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
   2056   Add<HBoundsCheck>(length, max_length);
   2057   return length;
   2058 }
   2059 
   2060 
   2061 HValue* HGraphBuilder::BuildCreateConsString(
   2062     HValue* length,
   2063     HValue* left,
   2064     HValue* right,
   2065     HAllocationMode allocation_mode) {
   2066   // Determine the string instance types.
   2067   HInstruction* left_instance_type = AddLoadStringInstanceType(left);
   2068   HInstruction* right_instance_type = AddLoadStringInstanceType(right);
   2069 
   2070   // Allocate the cons string object. HAllocate does not care whether we
   2071   // pass CONS_STRING_TYPE or CONS_ONE_BYTE_STRING_TYPE here, so we just use
   2072   // CONS_STRING_TYPE here. Below we decide whether the cons string is
   2073   // one-byte or two-byte and set the appropriate map.
   2074   DCHECK(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
   2075                                             CONS_ONE_BYTE_STRING_TYPE));
   2076   HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
   2077                                     HType::String(), CONS_STRING_TYPE,
   2078                                     allocation_mode);
   2079 
   2080   // Compute intersection and difference of instance types.
   2081   HValue* anded_instance_types = AddUncasted<HBitwise>(
   2082       Token::BIT_AND, left_instance_type, right_instance_type);
   2083   HValue* xored_instance_types = AddUncasted<HBitwise>(
   2084       Token::BIT_XOR, left_instance_type, right_instance_type);
   2085 
   2086   // We create a one-byte cons string if
   2087   // 1. both strings are one-byte, or
   2088   // 2. at least one of the strings is two-byte, but happens to contain only
   2089   //    one-byte characters.
   2090   // To do this, we check
   2091   // 1. if both strings are one-byte, or if the one-byte data hint is set in
   2092   //    both strings, or
   2093   // 2. if one of the strings has the one-byte data hint set and the other
   2094   //    string is one-byte.
   2095   IfBuilder if_onebyte(this);
   2096   STATIC_ASSERT(kOneByteStringTag != 0);
   2097   STATIC_ASSERT(kOneByteDataHintMask != 0);
   2098   if_onebyte.If<HCompareNumericAndBranch>(
   2099       AddUncasted<HBitwise>(
   2100           Token::BIT_AND, anded_instance_types,
   2101           Add<HConstant>(static_cast<int32_t>(
   2102                   kStringEncodingMask | kOneByteDataHintMask))),
   2103       graph()->GetConstant0(), Token::NE);
   2104   if_onebyte.Or();
   2105   STATIC_ASSERT(kOneByteStringTag != 0 &&
   2106                 kOneByteDataHintTag != 0 &&
   2107                 kOneByteDataHintTag != kOneByteStringTag);
   2108   if_onebyte.If<HCompareNumericAndBranch>(
   2109       AddUncasted<HBitwise>(
   2110           Token::BIT_AND, xored_instance_types,
   2111           Add<HConstant>(static_cast<int32_t>(
   2112                   kOneByteStringTag | kOneByteDataHintTag))),
   2113       Add<HConstant>(static_cast<int32_t>(
   2114               kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
   2115   if_onebyte.Then();
   2116   {
   2117     // We can safely skip the write barrier for storing the map here.
   2118     Add<HStoreNamedField>(
   2119         result, HObjectAccess::ForMap(),
   2120         Add<HConstant>(isolate()->factory()->cons_one_byte_string_map()));
   2121   }
   2122   if_onebyte.Else();
   2123   {
   2124     // We can safely skip the write barrier for storing the map here.
   2125     Add<HStoreNamedField>(
   2126         result, HObjectAccess::ForMap(),
   2127         Add<HConstant>(isolate()->factory()->cons_string_map()));
   2128   }
   2129   if_onebyte.End();
   2130 
   2131   // Initialize the cons string fields.
   2132   Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
   2133                         Add<HConstant>(String::kEmptyHashField));
   2134   Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
   2135   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
   2136   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
   2137 
   2138   // Count the native string addition.
   2139   AddIncrementCounter(isolate()->counters()->string_add_native());
   2140 
   2141   return result;
   2142 }
   2143 
   2144 
   2145 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
   2146                                             HValue* src_offset,
   2147                                             String::Encoding src_encoding,
   2148                                             HValue* dst,
   2149                                             HValue* dst_offset,
   2150                                             String::Encoding dst_encoding,
   2151                                             HValue* length) {
   2152   DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
   2153          src_encoding == String::ONE_BYTE_ENCODING);
   2154   LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
   2155   HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
   2156   {
   2157     HValue* src_index = AddUncasted<HAdd>(src_offset, index);
   2158     HValue* value =
   2159         AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
   2160     HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
   2161     Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
   2162   }
   2163   loop.EndBody();
   2164 }
   2165 
   2166 
   2167 HValue* HGraphBuilder::BuildObjectSizeAlignment(
   2168     HValue* unaligned_size, int header_size) {
   2169   DCHECK((header_size & kObjectAlignmentMask) == 0);
   2170   HValue* size = AddUncasted<HAdd>(
   2171       unaligned_size, Add<HConstant>(static_cast<int32_t>(
   2172           header_size + kObjectAlignmentMask)));
   2173   size->ClearFlag(HValue::kCanOverflow);
   2174   return AddUncasted<HBitwise>(
   2175       Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
   2176           ~kObjectAlignmentMask)));
   2177 }
   2178 
   2179 
   2180 HValue* HGraphBuilder::BuildUncheckedStringAdd(
   2181     HValue* left,
   2182     HValue* right,
   2183     HAllocationMode allocation_mode) {
   2184   // Determine the string lengths.
   2185   HValue* left_length = AddLoadStringLength(left);
   2186   HValue* right_length = AddLoadStringLength(right);
   2187 
   2188   // Compute the combined string length.
   2189   HValue* length = BuildAddStringLengths(left_length, right_length);
   2190 
   2191   // Do some manual constant folding here.
   2192   if (left_length->IsConstant()) {
   2193     HConstant* c_left_length = HConstant::cast(left_length);
   2194     DCHECK_NE(0, c_left_length->Integer32Value());
   2195     if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
   2196       // The right string contains at least one character.
   2197       return BuildCreateConsString(length, left, right, allocation_mode);
   2198     }
   2199   } else if (right_length->IsConstant()) {
   2200     HConstant* c_right_length = HConstant::cast(right_length);
   2201     DCHECK_NE(0, c_right_length->Integer32Value());
   2202     if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
   2203       // The left string contains at least one character.
   2204       return BuildCreateConsString(length, left, right, allocation_mode);
   2205     }
   2206   }
   2207 
   2208   // Check if we should create a cons string.
   2209   IfBuilder if_createcons(this);
   2210   if_createcons.If<HCompareNumericAndBranch>(
   2211       length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
   2212   if_createcons.Then();
   2213   {
   2214     // Create a cons string.
   2215     Push(BuildCreateConsString(length, left, right, allocation_mode));
   2216   }
   2217   if_createcons.Else();
   2218   {
   2219     // Determine the string instance types.
   2220     HValue* left_instance_type = AddLoadStringInstanceType(left);
   2221     HValue* right_instance_type = AddLoadStringInstanceType(right);
   2222 
   2223     // Compute union and difference of instance types.
   2224     HValue* ored_instance_types = AddUncasted<HBitwise>(
   2225         Token::BIT_OR, left_instance_type, right_instance_type);
   2226     HValue* xored_instance_types = AddUncasted<HBitwise>(
   2227         Token::BIT_XOR, left_instance_type, right_instance_type);
   2228 
   2229     // Check if both strings have the same encoding and both are
   2230     // sequential.
   2231     IfBuilder if_sameencodingandsequential(this);
   2232     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
   2233         AddUncasted<HBitwise>(
   2234             Token::BIT_AND, xored_instance_types,
   2235             Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
   2236         graph()->GetConstant0(), Token::EQ);
   2237     if_sameencodingandsequential.And();
   2238     STATIC_ASSERT(kSeqStringTag == 0);
   2239     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
   2240         AddUncasted<HBitwise>(
   2241             Token::BIT_AND, ored_instance_types,
   2242             Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
   2243         graph()->GetConstant0(), Token::EQ);
   2244     if_sameencodingandsequential.Then();
   2245     {
   2246       HConstant* string_map =
   2247           Add<HConstant>(isolate()->factory()->string_map());
   2248       HConstant* one_byte_string_map =
   2249           Add<HConstant>(isolate()->factory()->one_byte_string_map());
   2250 
   2251       // Determine map and size depending on whether result is one-byte string.
   2252       IfBuilder if_onebyte(this);
   2253       STATIC_ASSERT(kOneByteStringTag != 0);
   2254       if_onebyte.If<HCompareNumericAndBranch>(
   2255           AddUncasted<HBitwise>(
   2256               Token::BIT_AND, ored_instance_types,
   2257               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
   2258           graph()->GetConstant0(), Token::NE);
   2259       if_onebyte.Then();
   2260       {
   2261         // Allocate sequential one-byte string object.
   2262         Push(length);
   2263         Push(one_byte_string_map);
   2264       }
   2265       if_onebyte.Else();
   2266       {
   2267         // Allocate sequential two-byte string object.
   2268         HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
   2269         size->ClearFlag(HValue::kCanOverflow);
   2270         size->SetFlag(HValue::kUint32);
   2271         Push(size);
   2272         Push(string_map);
   2273       }
   2274       if_onebyte.End();
   2275       HValue* map = Pop();
   2276 
   2277       // Calculate the number of bytes needed for the characters in the
   2278       // string while observing object alignment.
   2279       STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
   2280       HValue* size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);
   2281 
   2282       // Allocate the string object. HAllocate does not care whether we pass
   2283       // STRING_TYPE or ONE_BYTE_STRING_TYPE here, so we just use STRING_TYPE.
   2284       HAllocate* result = BuildAllocate(
   2285           size, HType::String(), STRING_TYPE, allocation_mode);
   2286       Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
   2287 
   2288       // Initialize the string fields.
   2289       Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
   2290                             Add<HConstant>(String::kEmptyHashField));
   2291       Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
   2292 
   2293       // Copy characters to the result string.
   2294       IfBuilder if_twobyte(this);
   2295       if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
   2296       if_twobyte.Then();
   2297       {
   2298         // Copy characters from the left string.
   2299         BuildCopySeqStringChars(
   2300             left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
   2301             result, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
   2302             left_length);
   2303 
   2304         // Copy characters from the right string.
   2305         BuildCopySeqStringChars(
   2306             right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING,
   2307             result, left_length, String::TWO_BYTE_ENCODING,
   2308             right_length);
   2309       }
   2310       if_twobyte.Else();
   2311       {
   2312         // Copy characters from the left string.
   2313         BuildCopySeqStringChars(
   2314             left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
   2315             result, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
   2316             left_length);
   2317 
   2318         // Copy characters from the right string.
   2319         BuildCopySeqStringChars(
   2320             right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING,
   2321             result, left_length, String::ONE_BYTE_ENCODING,
   2322             right_length);
   2323       }
   2324       if_twobyte.End();
   2325 
   2326       // Count the native string addition.
   2327       AddIncrementCounter(isolate()->counters()->string_add_native());
   2328 
   2329       // Return the sequential string.
   2330       Push(result);
   2331     }
   2332     if_sameencodingandsequential.Else();
   2333     {
   2334       // Fallback to the runtime to add the two strings.
   2335       Add<HPushArguments>(left, right);
   2336       Push(Add<HCallRuntime>(
   2337             isolate()->factory()->empty_string(),
   2338             Runtime::FunctionForId(Runtime::kStringAdd),
   2339             2));
   2340     }
   2341     if_sameencodingandsequential.End();
   2342   }
   2343   if_createcons.End();
   2344 
   2345   return Pop();
   2346 }
   2347 
   2348 
   2349 HValue* HGraphBuilder::BuildStringAdd(
   2350     HValue* left,
   2351     HValue* right,
   2352     HAllocationMode allocation_mode) {
   2353   NoObservableSideEffectsScope no_effects(this);
   2354 
   2355   // Determine string lengths.
   2356   HValue* left_length = AddLoadStringLength(left);
   2357   HValue* right_length = AddLoadStringLength(right);
   2358 
   2359   // Check if left string is empty.
   2360   IfBuilder if_leftempty(this);
   2361   if_leftempty.If<HCompareNumericAndBranch>(
   2362       left_length, graph()->GetConstant0(), Token::EQ);
   2363   if_leftempty.Then();
   2364   {
   2365     // Count the native string addition.
   2366     AddIncrementCounter(isolate()->counters()->string_add_native());
   2367 
   2368     // Just return the right string.
   2369     Push(right);
   2370   }
   2371   if_leftempty.Else();
   2372   {
   2373     // Check if right string is empty.
   2374     IfBuilder if_rightempty(this);
   2375     if_rightempty.If<HCompareNumericAndBranch>(
   2376         right_length, graph()->GetConstant0(), Token::EQ);
   2377     if_rightempty.Then();
   2378     {
   2379       // Count the native string addition.
   2380       AddIncrementCounter(isolate()->counters()->string_add_native());
   2381 
   2382       // Just return the left string.
   2383       Push(left);
   2384     }
   2385     if_rightempty.Else();
   2386     {
   2387       // Add the two non-empty strings.
   2388       Push(BuildUncheckedStringAdd(left, right, allocation_mode));
   2389     }
   2390     if_rightempty.End();
   2391   }
   2392   if_leftempty.End();
   2393 
   2394   return Pop();
   2395 }
   2396 
   2397 
   2398 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
   2399     HValue* checked_object,
   2400     HValue* key,
   2401     HValue* val,
   2402     bool is_js_array,
   2403     ElementsKind elements_kind,
   2404     PropertyAccessType access_type,
   2405     LoadKeyedHoleMode load_mode,
   2406     KeyedAccessStoreMode store_mode) {
   2407   DCHECK((!IsExternalArrayElementsKind(elements_kind) &&
   2408               !IsFixedTypedArrayElementsKind(elements_kind)) ||
   2409          !is_js_array);
   2410   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
   2411   // on a HElementsTransition instruction. The flag can also be removed if the
   2412   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
   2413   // ElementsKind transitions. Finally, the dependency can be removed for stores
   2414   // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
   2415   // generated store code.
   2416   if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
   2417       (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
   2418     checked_object->ClearDependsOnFlag(kElementsKind);
   2419   }
   2420 
   2421   bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
   2422   bool fast_elements = IsFastObjectElementsKind(elements_kind);
   2423   HValue* elements = AddLoadElements(checked_object);
   2424   if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
   2425       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
   2426     HCheckMaps* check_cow_map = Add<HCheckMaps>(
   2427         elements, isolate()->factory()->fixed_array_map());
   2428     check_cow_map->ClearDependsOnFlag(kElementsKind);
   2429   }
   2430   HInstruction* length = NULL;
   2431   if (is_js_array) {
   2432     length = Add<HLoadNamedField>(
   2433         checked_object->ActualValue(), checked_object,
   2434         HObjectAccess::ForArrayLength(elements_kind));
   2435   } else {
   2436     length = AddLoadFixedArrayLength(elements);
   2437   }
   2438   length->set_type(HType::Smi());
   2439   HValue* checked_key = NULL;
   2440   if (IsExternalArrayElementsKind(elements_kind) ||
   2441       IsFixedTypedArrayElementsKind(elements_kind)) {
   2442     HValue* backing_store;
   2443     if (IsExternalArrayElementsKind(elements_kind)) {
   2444       backing_store = Add<HLoadNamedField>(
   2445           elements, static_cast<HValue*>(NULL),
   2446           HObjectAccess::ForExternalArrayExternalPointer());
   2447     } else {
   2448       backing_store = elements;
   2449     }
   2450     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
   2451       NoObservableSideEffectsScope no_effects(this);
   2452       IfBuilder length_checker(this);
   2453       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
   2454       length_checker.Then();
   2455       IfBuilder negative_checker(this);
   2456       HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
   2457           key, graph()->GetConstant0(), Token::GTE);
   2458       negative_checker.Then();
   2459       HInstruction* result = AddElementAccess(
   2460           backing_store, key, val, bounds_check, elements_kind, access_type);
   2461       negative_checker.ElseDeopt("Negative key encountered");
   2462       negative_checker.End();
   2463       length_checker.End();
   2464       return result;
   2465     } else {
   2466       DCHECK(store_mode == STANDARD_STORE);
   2467       checked_key = Add<HBoundsCheck>(key, length);
   2468       return AddElementAccess(
   2469           backing_store, checked_key, val,
   2470           checked_object, elements_kind, access_type);
   2471     }
   2472   }
   2473   DCHECK(fast_smi_only_elements ||
   2474          fast_elements ||
   2475          IsFastDoubleElementsKind(elements_kind));
   2476 
   2477   // In case val is stored into a fast smi array, assure that the value is a smi
   2478   // before manipulating the backing store. Otherwise the actual store may
   2479   // deopt, leaving the backing store in an invalid state.
   2480   if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
   2481       !val->type().IsSmi()) {
   2482     val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
   2483   }
   2484 
   2485   if (IsGrowStoreMode(store_mode)) {
   2486     NoObservableSideEffectsScope no_effects(this);
   2487     Representation representation = HStoreKeyed::RequiredValueRepresentation(
   2488         elements_kind, STORE_TO_INITIALIZED_ENTRY);
   2489     val = AddUncasted<HForceRepresentation>(val, representation);
   2490     elements = BuildCheckForCapacityGrow(checked_object, elements,
   2491                                          elements_kind, length, key,
   2492                                          is_js_array, access_type);
   2493     checked_key = key;
   2494   } else {
   2495     checked_key = Add<HBoundsCheck>(key, length);
   2496 
   2497     if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
   2498       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
   2499         NoObservableSideEffectsScope no_effects(this);
   2500         elements = BuildCopyElementsOnWrite(checked_object, elements,
   2501                                             elements_kind, length);
   2502       } else {
   2503         HCheckMaps* check_cow_map = Add<HCheckMaps>(
   2504             elements, isolate()->factory()->fixed_array_map());
   2505         check_cow_map->ClearDependsOnFlag(kElementsKind);
   2506       }
   2507     }
   2508   }
   2509   return AddElementAccess(elements, checked_key, val, checked_object,
   2510                           elements_kind, access_type, load_mode);
   2511 }
   2512 
   2513 
   2514 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
   2515     JSArrayBuilder* array_builder,
   2516     HValue* length_argument) {
   2517   if (length_argument->IsConstant() &&
   2518       HConstant::cast(length_argument)->HasSmiValue()) {
   2519     int array_length = HConstant::cast(length_argument)->Integer32Value();
   2520     if (array_length == 0) {
   2521       return array_builder->AllocateEmptyArray();
   2522     } else {
   2523       return array_builder->AllocateArray(length_argument,
   2524                                           array_length,
   2525                                           length_argument);
   2526     }
   2527   }
   2528 
   2529   HValue* constant_zero = graph()->GetConstant0();
   2530   HConstant* max_alloc_length =
   2531       Add<HConstant>(JSObject::kInitialMaxFastElementArray);
   2532   HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
   2533                                                    max_alloc_length);
   2534   IfBuilder if_builder(this);
   2535   if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
   2536                                           Token::EQ);
   2537   if_builder.Then();
   2538   const int initial_capacity = JSArray::kPreallocatedArrayElements;
   2539   HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
   2540   Push(initial_capacity_node);  // capacity
   2541   Push(constant_zero);          // length
   2542   if_builder.Else();
   2543   if (!(top_info()->IsStub()) &&
   2544       IsFastPackedElementsKind(array_builder->kind())) {
   2545     // We'll come back later with better (holey) feedback.
   2546     if_builder.Deopt("Holey array despite packed elements_kind feedback");
   2547   } else {
   2548     Push(checked_length);         // capacity
   2549     Push(checked_length);         // length
   2550   }
   2551   if_builder.End();
   2552 
   2553   // Figure out total size
   2554   HValue* length = Pop();
   2555   HValue* capacity = Pop();
   2556   return array_builder->AllocateArray(capacity, max_alloc_length, length);
   2557 }
   2558 
   2559 
   2560 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
   2561                                                   HValue* capacity) {
   2562   int elements_size = IsFastDoubleElementsKind(kind)
   2563       ? kDoubleSize
   2564       : kPointerSize;
   2565 
   2566   HConstant* elements_size_value = Add<HConstant>(elements_size);
   2567   HInstruction* mul = HMul::NewImul(zone(), context(),
   2568                                     capacity->ActualValue(),
   2569                                     elements_size_value);
   2570   AddInstruction(mul);
   2571   mul->ClearFlag(HValue::kCanOverflow);
   2572 
   2573   STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
   2574 
   2575   HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
   2576   HValue* total_size = AddUncasted<HAdd>(mul, header_size);
   2577   total_size->ClearFlag(HValue::kCanOverflow);
   2578   return total_size;
   2579 }
   2580 
   2581 
   2582 HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
   2583   int base_size = JSArray::kSize;
   2584   if (mode == TRACK_ALLOCATION_SITE) {
   2585     base_size += AllocationMemento::kSize;
   2586   }
   2587   HConstant* size_in_bytes = Add<HConstant>(base_size);
   2588   return Add<HAllocate>(
   2589       size_in_bytes, HType::JSArray(), NOT_TENURED, JS_OBJECT_TYPE);
   2590 }
   2591 
   2592 
   2593 HConstant* HGraphBuilder::EstablishElementsAllocationSize(
   2594     ElementsKind kind,
   2595     int capacity) {
   2596   int base_size = IsFastDoubleElementsKind(kind)
   2597       ? FixedDoubleArray::SizeFor(capacity)
   2598       : FixedArray::SizeFor(capacity);
   2599 
   2600   return Add<HConstant>(base_size);
   2601 }
   2602 
   2603 
   2604 HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
   2605                                                 HValue* size_in_bytes) {
   2606   InstanceType instance_type = IsFastDoubleElementsKind(kind)
   2607       ? FIXED_DOUBLE_ARRAY_TYPE
   2608       : FIXED_ARRAY_TYPE;
   2609 
   2610   return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
   2611                         instance_type);
   2612 }
   2613 
   2614 
   2615 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
   2616                                                   ElementsKind kind,
   2617                                                   HValue* capacity) {
   2618   Factory* factory = isolate()->factory();
   2619   Handle<Map> map = IsFastDoubleElementsKind(kind)
   2620       ? factory->fixed_double_array_map()
   2621       : factory->fixed_array_map();
   2622 
   2623   Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map));
   2624   Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
   2625                         capacity);
   2626 }
   2627 
   2628 
   2629 HValue* HGraphBuilder::BuildAllocateElementsAndInitializeElementsHeader(
   2630     ElementsKind kind,
   2631     HValue* capacity) {
   2632   // The HForceRepresentation is to prevent possible deopt on int-smi
   2633   // conversion after allocation but before the new object fields are set.
   2634   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
   2635   HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
   2636   HValue* new_elements = BuildAllocateElements(kind, size_in_bytes);
   2637   BuildInitializeElementsHeader(new_elements, kind, capacity);
   2638   return new_elements;
   2639 }
   2640 
   2641 
   2642 void HGraphBuilder::BuildJSArrayHeader(HValue* array,
   2643                                        HValue* array_map,
   2644                                        HValue* elements,
   2645                                        AllocationSiteMode mode,
   2646                                        ElementsKind elements_kind,
   2647                                        HValue* allocation_site_payload,
   2648                                        HValue* length_field) {
   2649   Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
   2650 
   2651   HConstant* empty_fixed_array =
   2652     Add<HConstant>(isolate()->factory()->empty_fixed_array());
   2653 
   2654   Add<HStoreNamedField>(
   2655       array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
   2656 
   2657   Add<HStoreNamedField>(
   2658       array, HObjectAccess::ForElementsPointer(),
   2659       elements != NULL ? elements : empty_fixed_array);
   2660 
   2661   Add<HStoreNamedField>(
   2662       array, HObjectAccess::ForArrayLength(elements_kind), length_field);
   2663 
   2664   if (mode == TRACK_ALLOCATION_SITE) {
   2665     BuildCreateAllocationMemento(
   2666         array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
   2667   }
   2668 }
   2669 
   2670 
   2671 HInstruction* HGraphBuilder::AddElementAccess(
   2672     HValue* elements,
   2673     HValue* checked_key,
   2674     HValue* val,
   2675     HValue* dependency,
   2676     ElementsKind elements_kind,
   2677     PropertyAccessType access_type,
   2678     LoadKeyedHoleMode load_mode) {
   2679   if (access_type == STORE) {
   2680     DCHECK(val != NULL);
   2681     if (elements_kind == EXTERNAL_UINT8_CLAMPED_ELEMENTS ||
   2682         elements_kind == UINT8_CLAMPED_ELEMENTS) {
   2683       val = Add<HClampToUint8>(val);
   2684     }
   2685     return Add<HStoreKeyed>(elements, checked_key, val, elements_kind,
   2686                             STORE_TO_INITIALIZED_ENTRY);
   2687   }
   2688 
   2689   DCHECK(access_type == LOAD);
   2690   DCHECK(val == NULL);
   2691   HLoadKeyed* load = Add<HLoadKeyed>(
   2692       elements, checked_key, dependency, elements_kind, load_mode);
   2693   if (FLAG_opt_safe_uint32_operations &&
   2694       (elements_kind == EXTERNAL_UINT32_ELEMENTS ||
   2695        elements_kind == UINT32_ELEMENTS)) {
   2696     graph()->RecordUint32Instruction(load);
   2697   }
   2698   return load;
   2699 }
   2700 
   2701 
   2702 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
   2703                                            HValue* dependency) {
   2704   return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
   2705 }
   2706 
   2707 
   2708 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
   2709                                                 HValue* dependency) {
   2710   return Add<HLoadNamedField>(
   2711       object, dependency, HObjectAccess::ForElementsPointer());
   2712 }
   2713 
   2714 
   2715 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
   2716     HValue* array,
   2717     HValue* dependency) {
   2718   return Add<HLoadNamedField>(
   2719       array, dependency, HObjectAccess::ForFixedArrayLength());
   2720 }
   2721 
   2722 
   2723 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array,
   2724                                                    ElementsKind kind,
   2725                                                    HValue* dependency) {
   2726   return Add<HLoadNamedField>(
   2727       array, dependency, HObjectAccess::ForArrayLength(kind));
   2728 }
   2729 
   2730 
   2731 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
   2732   HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
   2733                                                 graph_->GetConstant1());
   2734 
   2735   HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
   2736   new_capacity->ClearFlag(HValue::kCanOverflow);
   2737 
   2738   HValue* min_growth = Add<HConstant>(16);
   2739 
   2740   new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
   2741   new_capacity->ClearFlag(HValue::kCanOverflow);
   2742 
   2743   return new_capacity;
   2744 }
   2745 
   2746 
   2747 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
   2748                                                  HValue* elements,
   2749                                                  ElementsKind kind,
   2750                                                  ElementsKind new_kind,
   2751                                                  HValue* length,
   2752                                                  HValue* new_capacity) {
   2753   Add<HBoundsCheck>(new_capacity, Add<HConstant>(
   2754           (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
   2755           ElementsKindToShiftSize(new_kind)));
   2756 
   2757   HValue* new_elements = BuildAllocateElementsAndInitializeElementsHeader(
   2758       new_kind, new_capacity);
   2759 
   2760   BuildCopyElements(elements, kind, new_elements,
   2761                     new_kind, length, new_capacity);
   2762 
   2763   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   2764                         new_elements);
   2765 
   2766   return new_elements;
   2767 }
   2768 
   2769 
   2770 void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
   2771                                                ElementsKind elements_kind,
   2772                                                HValue* from,
   2773                                                HValue* to,
   2774                                                HValue* value) {
   2775   if (to == NULL) {
   2776     to = AddLoadFixedArrayLength(elements);
   2777   }
   2778 
   2779   // Special loop unfolding case
   2780   STATIC_ASSERT(JSArray::kPreallocatedArrayElements <=
   2781                 kElementLoopUnrollThreshold);
   2782   int initial_capacity = -1;
   2783   if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
   2784     int constant_from = from->GetInteger32Constant();
   2785     int constant_to = to->GetInteger32Constant();
   2786 
   2787     if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
   2788       initial_capacity = constant_to;
   2789     }
   2790   }
   2791 
   2792   // Since we're about to store a hole value, the store instruction below must
   2793   // assume an elements kind that supports heap object values.
   2794   if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   2795     elements_kind = FAST_HOLEY_ELEMENTS;
   2796   }
   2797 
   2798   if (initial_capacity >= 0) {
   2799     for (int i = 0; i < initial_capacity; i++) {
   2800       HInstruction* key = Add<HConstant>(i);
   2801       Add<HStoreKeyed>(elements, key, value, elements_kind);
   2802     }
   2803   } else {
   2804     // Carefully loop backwards so that the "from" remains live through the loop
   2805     // rather than the to. This often corresponds to keeping length live rather
   2806     // then capacity, which helps register allocation, since length is used more
   2807     // other than capacity after filling with holes.
   2808     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   2809 
   2810     HValue* key = builder.BeginBody(to, from, Token::GT);
   2811 
   2812     HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
   2813     adjusted_key->ClearFlag(HValue::kCanOverflow);
   2814 
   2815     Add<HStoreKeyed>(elements, adjusted_key, value, elements_kind);
   2816 
   2817     builder.EndBody();
   2818   }
   2819 }
   2820 
   2821 
   2822 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
   2823                                               ElementsKind elements_kind,
   2824                                               HValue* from,
   2825                                               HValue* to) {
   2826   // Fast elements kinds need to be initialized in case statements below cause a
   2827   // garbage collection.
   2828   Factory* factory = isolate()->factory();
   2829 
   2830   double nan_double = FixedDoubleArray::hole_nan_as_double();
   2831   HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
   2832       ? Add<HConstant>(factory->the_hole_value())
   2833       : Add<HConstant>(nan_double);
   2834 
   2835   BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
   2836 }
   2837 
   2838 
   2839 void HGraphBuilder::BuildCopyElements(HValue* from_elements,
   2840                                       ElementsKind from_elements_kind,
   2841                                       HValue* to_elements,
   2842                                       ElementsKind to_elements_kind,
   2843                                       HValue* length,
   2844                                       HValue* capacity) {
   2845   int constant_capacity = -1;
   2846   if (capacity != NULL &&
   2847       capacity->IsConstant() &&
   2848       HConstant::cast(capacity)->HasInteger32Value()) {
   2849     int constant_candidate = HConstant::cast(capacity)->Integer32Value();
   2850     if (constant_candidate <= kElementLoopUnrollThreshold) {
   2851       constant_capacity = constant_candidate;
   2852     }
   2853   }
   2854 
   2855   bool pre_fill_with_holes =
   2856     IsFastDoubleElementsKind(from_elements_kind) &&
   2857     IsFastObjectElementsKind(to_elements_kind);
   2858   if (pre_fill_with_holes) {
   2859     // If the copy might trigger a GC, make sure that the FixedArray is
   2860     // pre-initialized with holes to make sure that it's always in a
   2861     // consistent state.
   2862     BuildFillElementsWithHole(to_elements, to_elements_kind,
   2863                               graph()->GetConstant0(), NULL);
   2864   }
   2865 
   2866   if (constant_capacity != -1) {
   2867     // Unroll the loop for small elements kinds.
   2868     for (int i = 0; i < constant_capacity; i++) {
   2869       HValue* key_constant = Add<HConstant>(i);
   2870       HInstruction* value = Add<HLoadKeyed>(from_elements, key_constant,
   2871                                             static_cast<HValue*>(NULL),
   2872                                             from_elements_kind);
   2873       Add<HStoreKeyed>(to_elements, key_constant, value, to_elements_kind);
   2874     }
   2875   } else {
   2876     if (!pre_fill_with_holes &&
   2877         (capacity == NULL || !length->Equals(capacity))) {
   2878       BuildFillElementsWithHole(to_elements, to_elements_kind,
   2879                                 length, NULL);
   2880     }
   2881 
   2882     if (capacity == NULL) {
   2883       capacity = AddLoadFixedArrayLength(to_elements);
   2884     }
   2885 
   2886     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   2887 
   2888     HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
   2889                                     Token::GT);
   2890 
   2891     key = AddUncasted<HSub>(key, graph()->GetConstant1());
   2892     key->ClearFlag(HValue::kCanOverflow);
   2893 
   2894     HValue* element = Add<HLoadKeyed>(from_elements, key,
   2895                                       static_cast<HValue*>(NULL),
   2896                                       from_elements_kind,
   2897                                       ALLOW_RETURN_HOLE);
   2898 
   2899     ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
   2900                          IsFastSmiElementsKind(to_elements_kind))
   2901       ? FAST_HOLEY_ELEMENTS : to_elements_kind;
   2902 
   2903     if (IsHoleyElementsKind(from_elements_kind) &&
   2904         from_elements_kind != to_elements_kind) {
   2905       IfBuilder if_hole(this);
   2906       if_hole.If<HCompareHoleAndBranch>(element);
   2907       if_hole.Then();
   2908       HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
   2909         ? Add<HConstant>(FixedDoubleArray::hole_nan_as_double())
   2910         : graph()->GetConstantHole();
   2911       Add<HStoreKeyed>(to_elements, key, hole_constant, kind);
   2912       if_hole.Else();
   2913       HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
   2914       store->SetFlag(HValue::kAllowUndefinedAsNaN);
   2915       if_hole.End();
   2916     } else {
   2917       HStoreKeyed* store = Add<HStoreKeyed>(to_elements, key, element, kind);
   2918       store->SetFlag(HValue::kAllowUndefinedAsNaN);
   2919     }
   2920 
   2921     builder.EndBody();
   2922   }
   2923 
   2924   Counters* counters = isolate()->counters();
   2925   AddIncrementCounter(counters->inlined_copied_elements());
   2926 }
   2927 
   2928 
   2929 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate,
   2930                                                  HValue* allocation_site,
   2931                                                  AllocationSiteMode mode,
   2932                                                  ElementsKind kind) {
   2933   HAllocate* array = AllocateJSArrayObject(mode);
   2934 
   2935   HValue* map = AddLoadMap(boilerplate);
   2936   HValue* elements = AddLoadElements(boilerplate);
   2937   HValue* length = AddLoadArrayLength(boilerplate, kind);
   2938 
   2939   BuildJSArrayHeader(array,
   2940                      map,
   2941                      elements,
   2942                      mode,
   2943                      FAST_ELEMENTS,
   2944                      allocation_site,
   2945                      length);
   2946   return array;
   2947 }
   2948 
   2949 
   2950 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate,
   2951                                                    HValue* allocation_site,
   2952                                                    AllocationSiteMode mode) {
   2953   HAllocate* array = AllocateJSArrayObject(mode);
   2954 
   2955   HValue* map = AddLoadMap(boilerplate);
   2956 
   2957   BuildJSArrayHeader(array,
   2958                      map,
   2959                      NULL,  // set elements to empty fixed array
   2960                      mode,
   2961                      FAST_ELEMENTS,
   2962                      allocation_site,
   2963                      graph()->GetConstant0());
   2964   return array;
   2965 }
   2966 
   2967 
   2968 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
   2969                                                       HValue* allocation_site,
   2970                                                       AllocationSiteMode mode,
   2971                                                       ElementsKind kind) {
   2972   HValue* boilerplate_elements = AddLoadElements(boilerplate);
   2973   HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements);
   2974 
   2975   // Generate size calculation code here in order to make it dominate
   2976   // the JSArray allocation.
   2977   HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
   2978 
   2979   // Create empty JSArray object for now, store elimination should remove
   2980   // redundant initialization of elements and length fields and at the same
   2981   // time the object will be fully prepared for GC if it happens during
   2982   // elements allocation.
   2983   HValue* result = BuildCloneShallowArrayEmpty(
   2984       boilerplate, allocation_site, mode);
   2985 
   2986   HAllocate* elements = BuildAllocateElements(kind, elements_size);
   2987 
   2988   // This function implicitly relies on the fact that the
   2989   // FastCloneShallowArrayStub is called only for literals shorter than
   2990   // JSObject::kInitialMaxFastElementArray.
   2991   // Can't add HBoundsCheck here because otherwise the stub will eager a frame.
   2992   HConstant* size_upper_bound = EstablishElementsAllocationSize(
   2993       kind, JSObject::kInitialMaxFastElementArray);
   2994   elements->set_size_upper_bound(size_upper_bound);
   2995 
   2996   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), elements);
   2997 
   2998   // The allocation for the cloned array above causes register pressure on
   2999   // machines with low register counts. Force a reload of the boilerplate
   3000   // elements here to free up a register for the allocation to avoid unnecessary
   3001   // spillage.
   3002   boilerplate_elements = AddLoadElements(boilerplate);
   3003   boilerplate_elements->SetFlag(HValue::kCantBeReplaced);
   3004 
   3005   // Copy the elements array header.
   3006   for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
   3007     HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
   3008     Add<HStoreNamedField>(elements, access,
   3009         Add<HLoadNamedField>(boilerplate_elements,
   3010                              static_cast<HValue*>(NULL), access));
   3011   }
   3012 
   3013   // And the result of the length
   3014   HValue* length = AddLoadArrayLength(boilerplate, kind);
   3015   Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), length);
   3016 
   3017   BuildCopyElements(boilerplate_elements, kind, elements,
   3018                     kind, length, NULL);
   3019   return result;
   3020 }
   3021 
   3022 
   3023 void HGraphBuilder::BuildCompareNil(
   3024     HValue* value,
   3025     Type* type,
   3026     HIfContinuation* continuation) {
   3027   IfBuilder if_nil(this);
   3028   bool some_case_handled = false;
   3029   bool some_case_missing = false;
   3030 
   3031   if (type->Maybe(Type::Null())) {
   3032     if (some_case_handled) if_nil.Or();
   3033     if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
   3034     some_case_handled = true;
   3035   } else {
   3036     some_case_missing = true;
   3037   }
   3038 
   3039   if (type->Maybe(Type::Undefined())) {
   3040     if (some_case_handled) if_nil.Or();
   3041     if_nil.If<HCompareObjectEqAndBranch>(value,
   3042                                          graph()->GetConstantUndefined());
   3043     some_case_handled = true;
   3044   } else {
   3045     some_case_missing = true;
   3046   }
   3047 
   3048   if (type->Maybe(Type::Undetectable())) {
   3049     if (some_case_handled) if_nil.Or();
   3050     if_nil.If<HIsUndetectableAndBranch>(value);
   3051     some_case_handled = true;
   3052   } else {
   3053     some_case_missing = true;
   3054   }
   3055 
   3056   if (some_case_missing) {
   3057     if_nil.Then();
   3058     if_nil.Else();
   3059     if (type->NumClasses() == 1) {
   3060       BuildCheckHeapObject(value);
   3061       // For ICs, the map checked below is a sentinel map that gets replaced by
   3062       // the monomorphic map when the code is used as a template to generate a
   3063       // new IC. For optimized functions, there is no sentinel map, the map
   3064       // emitted below is the actual monomorphic map.
   3065       Add<HCheckMaps>(value, type->Classes().Current());
   3066     } else {
   3067       if_nil.Deopt("Too many undetectable types");
   3068     }
   3069   }
   3070 
   3071   if_nil.CaptureContinuation(continuation);
   3072 }
   3073 
   3074 
   3075 void HGraphBuilder::BuildCreateAllocationMemento(
   3076     HValue* previous_object,
   3077     HValue* previous_object_size,
   3078     HValue* allocation_site) {
   3079   DCHECK(allocation_site != NULL);
   3080   HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
   3081       previous_object, previous_object_size, HType::HeapObject());
   3082   AddStoreMapConstant(
   3083       allocation_memento, isolate()->factory()->allocation_memento_map());
   3084   Add<HStoreNamedField>(
   3085       allocation_memento,
   3086       HObjectAccess::ForAllocationMementoSite(),
   3087       allocation_site);
   3088   if (FLAG_allocation_site_pretenuring) {
   3089     HValue* memento_create_count = Add<HLoadNamedField>(
   3090         allocation_site, static_cast<HValue*>(NULL),
   3091         HObjectAccess::ForAllocationSiteOffset(
   3092             AllocationSite::kPretenureCreateCountOffset));
   3093     memento_create_count = AddUncasted<HAdd>(
   3094         memento_create_count, graph()->GetConstant1());
   3095     // This smi value is reset to zero after every gc, overflow isn't a problem
   3096     // since the counter is bounded by the new space size.
   3097     memento_create_count->ClearFlag(HValue::kCanOverflow);
   3098     Add<HStoreNamedField>(
   3099         allocation_site, HObjectAccess::ForAllocationSiteOffset(
   3100             AllocationSite::kPretenureCreateCountOffset), memento_create_count);
   3101   }
   3102 }
   3103 
   3104 
   3105 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
   3106   // Get the global context, then the native context
   3107   HInstruction* context =
   3108       Add<HLoadNamedField>(closure, static_cast<HValue*>(NULL),
   3109                            HObjectAccess::ForFunctionContextPointer());
   3110   HInstruction* global_object = Add<HLoadNamedField>(
   3111       context, static_cast<HValue*>(NULL),
   3112       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
   3113   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
   3114       GlobalObject::kNativeContextOffset);
   3115   return Add<HLoadNamedField>(
   3116       global_object, static_cast<HValue*>(NULL), access);
   3117 }
   3118 
   3119 
   3120 HInstruction* HGraphBuilder::BuildGetNativeContext() {
   3121   // Get the global context, then the native context
   3122   HValue* global_object = Add<HLoadNamedField>(
   3123       context(), static_cast<HValue*>(NULL),
   3124       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
   3125   return Add<HLoadNamedField>(
   3126       global_object, static_cast<HValue*>(NULL),
   3127       HObjectAccess::ForObservableJSObjectOffset(
   3128           GlobalObject::kNativeContextOffset));
   3129 }
   3130 
   3131 
   3132 HInstruction* HGraphBuilder::BuildGetArrayFunction() {
   3133   HInstruction* native_context = BuildGetNativeContext();
   3134   HInstruction* index =
   3135       Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
   3136   return Add<HLoadKeyed>(
   3137       native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
   3138 }
   3139 
   3140 
   3141 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
   3142     ElementsKind kind,
   3143     HValue* allocation_site_payload,
   3144     HValue* constructor_function,
   3145     AllocationSiteOverrideMode override_mode) :
   3146         builder_(builder),
   3147         kind_(kind),
   3148         allocation_site_payload_(allocation_site_payload),
   3149         constructor_function_(constructor_function) {
   3150   DCHECK(!allocation_site_payload->IsConstant() ||
   3151          HConstant::cast(allocation_site_payload)->handle(
   3152              builder_->isolate())->IsAllocationSite());
   3153   mode_ = override_mode == DISABLE_ALLOCATION_SITES
   3154       ? DONT_TRACK_ALLOCATION_SITE
   3155       : AllocationSite::GetMode(kind);
   3156 }
   3157 
   3158 
   3159 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
   3160                                               ElementsKind kind,
   3161                                               HValue* constructor_function) :
   3162     builder_(builder),
   3163     kind_(kind),
   3164     mode_(DONT_TRACK_ALLOCATION_SITE),
   3165     allocation_site_payload_(NULL),
   3166     constructor_function_(constructor_function) {
   3167 }
   3168 
   3169 
   3170 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
   3171   if (!builder()->top_info()->IsStub()) {
   3172     // A constant map is fine.
   3173     Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
   3174                     builder()->isolate());
   3175     return builder()->Add<HConstant>(map);
   3176   }
   3177 
   3178   if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
   3179     // No need for a context lookup if the kind_ matches the initial
   3180     // map, because we can just load the map in that case.
   3181     HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
   3182     return builder()->Add<HLoadNamedField>(
   3183         constructor_function_, static_cast<HValue*>(NULL), access);
   3184   }
   3185 
   3186   // TODO(mvstanton): we should always have a constructor function if we
   3187   // are creating a stub.
   3188   HInstruction* native_context = constructor_function_ != NULL
   3189       ? builder()->BuildGetNativeContext(constructor_function_)
   3190       : builder()->BuildGetNativeContext();
   3191 
   3192   HInstruction* index = builder()->Add<HConstant>(
   3193       static_cast<int32_t>(Context::JS_ARRAY_MAPS_INDEX));
   3194 
   3195   HInstruction* map_array = builder()->Add<HLoadKeyed>(
   3196       native_context, index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
   3197 
   3198   HInstruction* kind_index = builder()->Add<HConstant>(kind_);
   3199 
   3200   return builder()->Add<HLoadKeyed>(
   3201       map_array, kind_index, static_cast<HValue*>(NULL), FAST_ELEMENTS);
   3202 }
   3203 
   3204 
   3205 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
   3206   // Find the map near the constructor function
   3207   HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
   3208   return builder()->Add<HLoadNamedField>(
   3209       constructor_function_, static_cast<HValue*>(NULL), access);
   3210 }
   3211 
   3212 
   3213 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
   3214   HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
   3215   return AllocateArray(capacity,
   3216                        capacity,
   3217                        builder()->graph()->GetConstant0());
   3218 }
   3219 
   3220 
   3221 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
   3222     HValue* capacity,
   3223     HConstant* capacity_upper_bound,
   3224     HValue* length_field,
   3225     FillMode fill_mode) {
   3226   return AllocateArray(capacity,
   3227                        capacity_upper_bound->GetInteger32Constant(),
   3228                        length_field,
   3229                        fill_mode);
   3230 }
   3231 
   3232 
   3233 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
   3234     HValue* capacity,
   3235     int capacity_upper_bound,
   3236     HValue* length_field,
   3237     FillMode fill_mode) {
   3238   HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant()
   3239       ? HConstant::cast(capacity)
   3240       : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound);
   3241 
   3242   HAllocate* array = AllocateArray(capacity, length_field, fill_mode);
   3243   if (!elements_location_->has_size_upper_bound()) {
   3244     elements_location_->set_size_upper_bound(elememts_size_upper_bound);
   3245   }
   3246   return array;
   3247 }
   3248 
   3249 
   3250 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
   3251     HValue* capacity,
   3252     HValue* length_field,
   3253     FillMode fill_mode) {
   3254   // These HForceRepresentations are because we store these as fields in the
   3255   // objects we construct, and an int32-to-smi HChange could deopt. Accept
   3256   // the deopt possibility now, before allocation occurs.
   3257   capacity =
   3258       builder()->AddUncasted<HForceRepresentation>(capacity,
   3259                                                    Representation::Smi());
   3260   length_field =
   3261       builder()->AddUncasted<HForceRepresentation>(length_field,
   3262                                                    Representation::Smi());
   3263 
   3264   // Generate size calculation code here in order to make it dominate
   3265   // the JSArray allocation.
   3266   HValue* elements_size =
   3267       builder()->BuildCalculateElementsSize(kind_, capacity);
   3268 
   3269   // Allocate (dealing with failure appropriately)
   3270   HAllocate* array_object = builder()->AllocateJSArrayObject(mode_);
   3271 
   3272   // Fill in the fields: map, properties, length
   3273   HValue* map;
   3274   if (allocation_site_payload_ == NULL) {
   3275     map = EmitInternalMapCode();
   3276   } else {
   3277     map = EmitMapCode();
   3278   }
   3279 
   3280   builder()->BuildJSArrayHeader(array_object,
   3281                                 map,
   3282                                 NULL,  // set elements to empty fixed array
   3283                                 mode_,
   3284                                 kind_,
   3285                                 allocation_site_payload_,
   3286                                 length_field);
   3287 
   3288   // Allocate and initialize the elements
   3289   elements_location_ = builder()->BuildAllocateElements(kind_, elements_size);
   3290 
   3291   builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
   3292 
   3293   // Set the elements
   3294   builder()->Add<HStoreNamedField>(
   3295       array_object, HObjectAccess::ForElementsPointer(), elements_location_);
   3296 
   3297   if (fill_mode == FILL_WITH_HOLE) {
   3298     builder()->BuildFillElementsWithHole(elements_location_, kind_,
   3299                                          graph()->GetConstant0(), capacity);
   3300   }
   3301 
   3302   return array_object;
   3303 }
   3304 
   3305 
   3306 HValue* HGraphBuilder::AddLoadJSBuiltin(Builtins::JavaScript builtin) {
   3307   HValue* global_object = Add<HLoadNamedField>(
   3308       context(), static_cast<HValue*>(NULL),
   3309       HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
   3310   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
   3311       GlobalObject::kBuiltinsOffset);
   3312   HValue* builtins = Add<HLoadNamedField>(
   3313       global_object, static_cast<HValue*>(NULL), access);
   3314   HObjectAccess function_access = HObjectAccess::ForObservableJSObjectOffset(
   3315           JSBuiltinsObject::OffsetOfFunctionWithId(builtin));
   3316   return Add<HLoadNamedField>(
   3317       builtins, static_cast<HValue*>(NULL), function_access);
   3318 }
   3319 
   3320 
   3321 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
   3322     : HGraphBuilder(info),
   3323       function_state_(NULL),
   3324       initial_function_state_(this, info, NORMAL_RETURN, 0),
   3325       ast_context_(NULL),
   3326       break_scope_(NULL),
   3327       inlined_count_(0),
   3328       globals_(10, info->zone()),
   3329       osr_(new(info->zone()) HOsrBuilder(this)) {
   3330   // This is not initialized in the initializer list because the
   3331   // constructor for the initial state relies on function_state_ == NULL
   3332   // to know it's the initial state.
   3333   function_state_= &initial_function_state_;
   3334   InitializeAstVisitor(info->zone());
   3335   if (FLAG_hydrogen_track_positions) {
   3336     SetSourcePosition(info->shared_info()->start_position());
   3337   }
   3338 }
   3339 
   3340 
   3341 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
   3342                                                 HBasicBlock* second,
   3343                                                 BailoutId join_id) {
   3344   if (first == NULL) {
   3345     return second;
   3346   } else if (second == NULL) {
   3347     return first;
   3348   } else {
   3349     HBasicBlock* join_block = graph()->CreateBasicBlock();
   3350     Goto(first, join_block);
   3351     Goto(second, join_block);
   3352     join_block->SetJoinId(join_id);
   3353     return join_block;
   3354   }
   3355 }
   3356 
   3357 
   3358 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
   3359                                                   HBasicBlock* exit_block,
   3360                                                   HBasicBlock* continue_block) {
   3361   if (continue_block != NULL) {
   3362     if (exit_block != NULL) Goto(exit_block, continue_block);
   3363     continue_block->SetJoinId(statement->ContinueId());
   3364     return continue_block;
   3365   }
   3366   return exit_block;
   3367 }
   3368 
   3369 
   3370 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
   3371                                                 HBasicBlock* loop_entry,
   3372                                                 HBasicBlock* body_exit,
   3373                                                 HBasicBlock* loop_successor,
   3374                                                 HBasicBlock* break_block) {
   3375   if (body_exit != NULL) Goto(body_exit, loop_entry);
   3376   loop_entry->PostProcessLoopHeader(statement);
   3377   if (break_block != NULL) {
   3378     if (loop_successor != NULL) Goto(loop_successor, break_block);
   3379     break_block->SetJoinId(statement->ExitId());
   3380     return break_block;
   3381   }
   3382   return loop_successor;
   3383 }
   3384 
   3385 
   3386 // Build a new loop header block and set it as the current block.
   3387 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
   3388   HBasicBlock* loop_entry = CreateLoopHeaderBlock();
   3389   Goto(loop_entry);
   3390   set_current_block(loop_entry);
   3391   return loop_entry;
   3392 }
   3393 
   3394 
   3395 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
   3396     IterationStatement* statement) {
   3397   HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
   3398       ? osr()->BuildOsrLoopEntry(statement)
   3399       : BuildLoopEntry();
   3400   return loop_entry;
   3401 }
   3402 
   3403 
   3404 void HBasicBlock::FinishExit(HControlInstruction* instruction,
   3405                              HSourcePosition position) {
   3406   Finish(instruction, position);
   3407   ClearEnvironment();
   3408 }
   3409 
   3410 
   3411 OStream& operator<<(OStream& os, const HBasicBlock& b) {
   3412   return os << "B" << b.block_id();
   3413 }
   3414 
   3415 
   3416 HGraph::HGraph(CompilationInfo* info)
   3417     : isolate_(info->isolate()),
   3418       next_block_id_(0),
   3419       entry_block_(NULL),
   3420       blocks_(8, info->zone()),
   3421       values_(16, info->zone()),
   3422       phi_list_(NULL),
   3423       uint32_instructions_(NULL),
   3424       osr_(NULL),
   3425       info_(info),
   3426       zone_(info->zone()),
   3427       is_recursive_(false),
   3428       use_optimistic_licm_(false),
   3429       depends_on_empty_array_proto_elements_(false),
   3430       type_change_checksum_(0),
   3431       maximum_environment_size_(0),
   3432       no_side_effects_scope_count_(0),
   3433       disallow_adding_new_values_(false),
   3434       next_inline_id_(0),
   3435       inlined_functions_(5, info->zone()) {
   3436   if (info->IsStub()) {
   3437     CallInterfaceDescriptor descriptor =
   3438         info->code_stub()->GetCallInterfaceDescriptor();
   3439     start_environment_ = new (zone_)
   3440         HEnvironment(zone_, descriptor.GetEnvironmentParameterCount());
   3441   } else {
   3442     TraceInlinedFunction(info->shared_info(), HSourcePosition::Unknown());
   3443     start_environment_ =
   3444         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
   3445   }
   3446   start_environment_->set_ast_id(BailoutId::FunctionEntry());
   3447   entry_block_ = CreateBasicBlock();
   3448   entry_block_->SetInitialEnvironment(start_environment_);
   3449 }
   3450 
   3451 
   3452 HBasicBlock* HGraph::CreateBasicBlock() {
   3453   HBasicBlock* result = new(zone()) HBasicBlock(this);
   3454   blocks_.Add(result, zone());
   3455   return result;
   3456 }
   3457 
   3458 
   3459 void HGraph::FinalizeUniqueness() {
   3460   DisallowHeapAllocation no_gc;
   3461   DCHECK(!OptimizingCompilerThread::IsOptimizerThread(isolate()));
   3462   for (int i = 0; i < blocks()->length(); ++i) {
   3463     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
   3464       it.Current()->FinalizeUniqueness();
   3465     }
   3466   }
   3467 }
   3468 
   3469 
   3470 int HGraph::TraceInlinedFunction(
   3471     Handle<SharedFunctionInfo> shared,
   3472     HSourcePosition position) {
   3473   if (!FLAG_hydrogen_track_positions) {
   3474     return 0;
   3475   }
   3476 
   3477   int id = 0;
   3478   for (; id < inlined_functions_.length(); id++) {
   3479     if (inlined_functions_[id].shared().is_identical_to(shared)) {
   3480       break;
   3481     }
   3482   }
   3483 
   3484   if (id == inlined_functions_.length()) {
   3485     inlined_functions_.Add(InlinedFunctionInfo(shared), zone());
   3486 
   3487     if (!shared->script()->IsUndefined()) {
   3488       Handle<Script> script(Script::cast(shared->script()));
   3489       if (!script->source()->IsUndefined()) {
   3490         CodeTracer::Scope tracing_scopex(isolate()->GetCodeTracer());
   3491         OFStream os(tracing_scopex.file());
   3492         os << "--- FUNCTION SOURCE (" << shared->DebugName()->ToCString().get()
   3493            << ") id{" << info()->optimization_id() << "," << id << "} ---\n";
   3494         {
   3495           ConsStringIteratorOp op;
   3496           StringCharacterStream stream(String::cast(script->source()),
   3497                                        &op,
   3498                                        shared->start_position());
   3499           // fun->end_position() points to the last character in the stream. We
   3500           // need to compensate by adding one to calculate the length.
   3501           int source_len =
   3502               shared->end_position() - shared->start_position() + 1;
   3503           for (int i = 0; i < source_len; i++) {
   3504             if (stream.HasMore()) {
   3505               os << AsReversiblyEscapedUC16(stream.GetNext());
   3506             }
   3507           }
   3508         }
   3509 
   3510         os << "\n--- END ---\n";
   3511       }
   3512     }
   3513   }
   3514 
   3515   int inline_id = next_inline_id_++;
   3516 
   3517   if (inline_id != 0) {
   3518     CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
   3519     OFStream os(tracing_scope.file());
   3520     os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{"
   3521        << info()->optimization_id() << "," << id << "} AS " << inline_id
   3522        << " AT " << position << endl;
   3523   }
   3524 
   3525   return inline_id;
   3526 }
   3527 
   3528 
   3529 int HGraph::SourcePositionToScriptPosition(HSourcePosition pos) {
   3530   if (!FLAG_hydrogen_track_positions || pos.IsUnknown()) {
   3531     return pos.raw();
   3532   }
   3533 
   3534   return inlined_functions_[pos.inlining_id()].start_position() +
   3535       pos.position();
   3536 }
   3537 
   3538 
   3539 // Block ordering was implemented with two mutually recursive methods,
   3540 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
   3541 // The recursion could lead to stack overflow so the algorithm has been
   3542 // implemented iteratively.
   3543 // At a high level the algorithm looks like this:
   3544 //
   3545 // Postorder(block, loop_header) : {
   3546 //   if (block has already been visited or is of another loop) return;
   3547 //   mark block as visited;
   3548 //   if (block is a loop header) {
   3549 //     VisitLoopMembers(block, loop_header);
   3550 //     VisitSuccessorsOfLoopHeader(block);
   3551 //   } else {
   3552 //     VisitSuccessors(block)
   3553 //   }
   3554 //   put block in result list;
   3555 // }
   3556 //
   3557 // VisitLoopMembers(block, outer_loop_header) {
   3558 //   foreach (block b in block loop members) {
   3559 //     VisitSuccessorsOfLoopMember(b, outer_loop_header);
   3560 //     if (b is loop header) VisitLoopMembers(b);
   3561 //   }
   3562 // }
   3563 //
   3564 // VisitSuccessorsOfLoopMember(block, outer_loop_header) {
   3565 //   foreach (block b in block successors) Postorder(b, outer_loop_header)
   3566 // }
   3567 //
   3568 // VisitSuccessorsOfLoopHeader(block) {
   3569 //   foreach (block b in block successors) Postorder(b, block)
   3570 // }
   3571 //
   3572 // VisitSuccessors(block, loop_header) {
   3573 //   foreach (block b in block successors) Postorder(b, loop_header)
   3574 // }
   3575 //
   3576 // The ordering is started calling Postorder(entry, NULL).
   3577 //
   3578 // Each instance of PostorderProcessor represents the "stack frame" of the
   3579 // recursion, and particularly keeps the state of the loop (iteration) of the
   3580 // "Visit..." function it represents.
   3581 // To recycle memory we keep all the frames in a double linked list but
   3582 // this means that we cannot use constructors to initialize the frames.
   3583 //
   3584 class PostorderProcessor : public ZoneObject {
   3585  public:
   3586   // Back link (towards the stack bottom).
   3587   PostorderProcessor* parent() {return father_; }
   3588   // Forward link (towards the stack top).
   3589   PostorderProcessor* child() {return child_; }
   3590   HBasicBlock* block() { return block_; }
   3591   HLoopInformation* loop() { return loop_; }
   3592   HBasicBlock* loop_header() { return loop_header_; }
   3593 
   3594   static PostorderProcessor* CreateEntryProcessor(Zone* zone,
   3595                                                   HBasicBlock* block) {
   3596     PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
   3597     return result->SetupSuccessors(zone, block, NULL);
   3598   }
   3599 
   3600   PostorderProcessor* PerformStep(Zone* zone,
   3601                                   ZoneList<HBasicBlock*>* order) {
   3602     PostorderProcessor* next =
   3603         PerformNonBacktrackingStep(zone, order);
   3604     if (next != NULL) {
   3605       return next;
   3606     } else {
   3607       return Backtrack(zone, order);
   3608     }
   3609   }
   3610 
   3611  private:
   3612   explicit PostorderProcessor(PostorderProcessor* father)
   3613       : father_(father), child_(NULL), successor_iterator(NULL) { }
   3614 
   3615   // Each enum value states the cycle whose state is kept by this instance.
   3616   enum LoopKind {
   3617     NONE,
   3618     SUCCESSORS,
   3619     SUCCESSORS_OF_LOOP_HEADER,
   3620     LOOP_MEMBERS,
   3621     SUCCESSORS_OF_LOOP_MEMBER
   3622   };
   3623 
   3624   // Each "Setup..." method is like a constructor for a cycle state.
   3625   PostorderProcessor* SetupSuccessors(Zone* zone,
   3626                                       HBasicBlock* block,
   3627                                       HBasicBlock* loop_header) {
   3628     if (block == NULL || block->IsOrdered() ||
   3629         block->parent_loop_header() != loop_header) {
   3630       kind_ = NONE;
   3631       block_ = NULL;
   3632       loop_ = NULL;
   3633       loop_header_ = NULL;
   3634       return this;
   3635     } else {
   3636       block_ = block;
   3637       loop_ = NULL;
   3638       block->MarkAsOrdered();
   3639 
   3640       if (block->IsLoopHeader()) {
   3641         kind_ = SUCCESSORS_OF_LOOP_HEADER;
   3642         loop_header_ = block;
   3643         InitializeSuccessors();
   3644         PostorderProcessor* result = Push(zone);
   3645         return result->SetupLoopMembers(zone, block, block->loop_information(),
   3646                                         loop_header);
   3647       } else {
   3648         DCHECK(block->IsFinished());
   3649         kind_ = SUCCESSORS;
   3650         loop_header_ = loop_header;
   3651         InitializeSuccessors();
   3652         return this;
   3653       }
   3654     }
   3655   }
   3656 
   3657   PostorderProcessor* SetupLoopMembers(Zone* zone,
   3658                                        HBasicBlock* block,
   3659                                        HLoopInformation* loop,
   3660                                        HBasicBlock* loop_header) {
   3661     kind_ = LOOP_MEMBERS;
   3662     block_ = block;
   3663     loop_ = loop;
   3664     loop_header_ = loop_header;
   3665     InitializeLoopMembers();
   3666     return this;
   3667   }
   3668 
   3669   PostorderProcessor* SetupSuccessorsOfLoopMember(
   3670       HBasicBlock* block,
   3671       HLoopInformation* loop,
   3672       HBasicBlock* loop_header) {
   3673     kind_ = SUCCESSORS_OF_LOOP_MEMBER;
   3674     block_ = block;
   3675     loop_ = loop;
   3676     loop_header_ = loop_header;
   3677     InitializeSuccessors();
   3678     return this;
   3679   }
   3680 
   3681   // This method "allocates" a new stack frame.
   3682   PostorderProcessor* Push(Zone* zone) {
   3683     if (child_ == NULL) {
   3684       child_ = new(zone) PostorderProcessor(this);
   3685     }
   3686     return child_;
   3687   }
   3688 
   3689   void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) {
   3690     DCHECK(block_->end()->FirstSuccessor() == NULL ||
   3691            order->Contains(block_->end()->FirstSuccessor()) ||
   3692            block_->end()->FirstSuccessor()->IsLoopHeader());
   3693     DCHECK(block_->end()->SecondSuccessor() == NULL ||
   3694            order->Contains(block_->end()->SecondSuccessor()) ||
   3695            block_->end()->SecondSuccessor()->IsLoopHeader());
   3696     order->Add(block_, zone);
   3697   }
   3698 
   3699   // This method is the basic block to walk up the stack.
   3700   PostorderProcessor* Pop(Zone* zone,
   3701                           ZoneList<HBasicBlock*>* order) {
   3702     switch (kind_) {
   3703       case SUCCESSORS:
   3704       case SUCCESSORS_OF_LOOP_HEADER:
   3705         ClosePostorder(order, zone);
   3706         return father_;
   3707       case LOOP_MEMBERS:
   3708         return father_;
   3709       case SUCCESSORS_OF_LOOP_MEMBER:
   3710         if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
   3711           // In this case we need to perform a LOOP_MEMBERS cycle so we
   3712           // initialize it and return this instead of father.
   3713           return SetupLoopMembers(zone, block(),
   3714                                   block()->loop_information(), loop_header_);
   3715         } else {
   3716           return father_;
   3717         }
   3718       case NONE:
   3719         return father_;
   3720     }
   3721     UNREACHABLE();
   3722     return NULL;
   3723   }
   3724 
   3725   // Walks up the stack.
   3726   PostorderProcessor* Backtrack(Zone* zone,
   3727                                 ZoneList<HBasicBlock*>* order) {
   3728     PostorderProcessor* parent = Pop(zone, order);
   3729     while (parent != NULL) {
   3730       PostorderProcessor* next =
   3731           parent->PerformNonBacktrackingStep(zone, order);
   3732       if (next != NULL) {
   3733         return next;
   3734       } else {
   3735         parent = parent->Pop(zone, order);
   3736       }
   3737     }
   3738     return NULL;
   3739   }
   3740 
   3741   PostorderProcessor* PerformNonBacktrackingStep(
   3742       Zone* zone,
   3743       ZoneList<HBasicBlock*>* order) {
   3744     HBasicBlock* next_block;
   3745     switch (kind_) {
   3746       case SUCCESSORS:
   3747         next_block = AdvanceSuccessors();
   3748         if (next_block != NULL) {
   3749           PostorderProcessor* result = Push(zone);
   3750           return result->SetupSuccessors(zone, next_block, loop_header_);
   3751         }
   3752         break;
   3753       case SUCCESSORS_OF_LOOP_HEADER:
   3754         next_block = AdvanceSuccessors();
   3755         if (next_block != NULL) {
   3756           PostorderProcessor* result = Push(zone);
   3757           return result->SetupSuccessors(zone, next_block, block());
   3758         }
   3759         break;
   3760       case LOOP_MEMBERS:
   3761         next_block = AdvanceLoopMembers();
   3762         if (next_block != NULL) {
   3763           PostorderProcessor* result = Push(zone);
   3764           return result->SetupSuccessorsOfLoopMember(next_block,
   3765                                                      loop_, loop_header_);
   3766         }
   3767         break;
   3768       case SUCCESSORS_OF_LOOP_MEMBER:
   3769         next_block = AdvanceSuccessors();
   3770         if (next_block != NULL) {
   3771           PostorderProcessor* result = Push(zone);
   3772           return result->SetupSuccessors(zone, next_block, loop_header_);
   3773         }
   3774         break;
   3775       case NONE:
   3776         return NULL;
   3777     }
   3778     return NULL;
   3779   }
   3780 
   3781   // The following two methods implement a "foreach b in successors" cycle.
   3782   void InitializeSuccessors() {
   3783     loop_index = 0;
   3784     loop_length = 0;
   3785     successor_iterator = HSuccessorIterator(block_->end());
   3786   }
   3787 
   3788   HBasicBlock* AdvanceSuccessors() {
   3789     if (!successor_iterator.Done()) {
   3790       HBasicBlock* result = successor_iterator.Current();
   3791       successor_iterator.Advance();
   3792       return result;
   3793     }
   3794     return NULL;
   3795   }
   3796 
   3797   // The following two methods implement a "foreach b in loop members" cycle.
   3798   void InitializeLoopMembers() {
   3799     loop_index = 0;
   3800     loop_length = loop_->blocks()->length();
   3801   }
   3802 
   3803   HBasicBlock* AdvanceLoopMembers() {
   3804     if (loop_index < loop_length) {
   3805       HBasicBlock* result = loop_->blocks()->at(loop_index);
   3806       loop_index++;
   3807       return result;
   3808     } else {
   3809       return NULL;
   3810     }
   3811   }
   3812 
   3813   LoopKind kind_;
   3814   PostorderProcessor* father_;
   3815   PostorderProcessor* child_;
   3816   HLoopInformation* loop_;
   3817   HBasicBlock* block_;
   3818   HBasicBlock* loop_header_;
   3819   int loop_index;
   3820   int loop_length;
   3821   HSuccessorIterator successor_iterator;
   3822 };
   3823 
   3824 
   3825 void HGraph::OrderBlocks() {
   3826   CompilationPhase phase("H_Block ordering", info());
   3827 
   3828 #ifdef DEBUG
   3829   // Initially the blocks must not be ordered.
   3830   for (int i = 0; i < blocks_.length(); ++i) {
   3831     DCHECK(!blocks_[i]->IsOrdered());
   3832   }
   3833 #endif
   3834 
   3835   PostorderProcessor* postorder =
   3836       PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
   3837   blocks_.Rewind(0);
   3838   while (postorder) {
   3839     postorder = postorder->PerformStep(zone(), &blocks_);
   3840   }
   3841 
   3842 #ifdef DEBUG
   3843   // Now all blocks must be marked as ordered.
   3844   for (int i = 0; i < blocks_.length(); ++i) {
   3845     DCHECK(blocks_[i]->IsOrdered());
   3846   }
   3847 #endif
   3848 
   3849   // Reverse block list and assign block IDs.
   3850   for (int i = 0, j = blocks_.length(); --j >= i; ++i) {
   3851     HBasicBlock* bi = blocks_[i];
   3852     HBasicBlock* bj = blocks_[j];
   3853     bi->set_block_id(j);
   3854     bj->set_block_id(i);
   3855     blocks_[i] = bj;
   3856     blocks_[j] = bi;
   3857   }
   3858 }
   3859 
   3860 
   3861 void HGraph::AssignDominators() {
   3862   HPhase phase("H_Assign dominators", this);
   3863   for (int i = 0; i < blocks_.length(); ++i) {
   3864     HBasicBlock* block = blocks_[i];
   3865     if (block->IsLoopHeader()) {
   3866       // Only the first predecessor of a loop header is from outside the loop.
   3867       // All others are back edges, and thus cannot dominate the loop header.
   3868       block->AssignCommonDominator(block->predecessors()->first());
   3869       block->AssignLoopSuccessorDominators();
   3870     } else {
   3871       for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
   3872         blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
   3873       }
   3874     }
   3875   }
   3876 }
   3877 
   3878 
   3879 bool HGraph::CheckArgumentsPhiUses() {
   3880   int block_count = blocks_.length();
   3881   for (int i = 0; i < block_count; ++i) {
   3882     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   3883       HPhi* phi = blocks_[i]->phis()->at(j);
   3884       // We don't support phi uses of arguments for now.
   3885       if (phi->CheckFlag(HValue::kIsArguments)) return false;
   3886     }
   3887   }
   3888   return true;
   3889 }
   3890 
   3891 
   3892 bool HGraph::CheckConstPhiUses() {
   3893   int block_count = blocks_.length();
   3894   for (int i = 0; i < block_count; ++i) {
   3895     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   3896       HPhi* phi = blocks_[i]->phis()->at(j);
   3897       // Check for the hole value (from an uninitialized const).
   3898       for (int k = 0; k < phi->OperandCount(); k++) {
   3899         if (phi->OperandAt(k) == GetConstantHole()) return false;
   3900       }
   3901     }
   3902   }
   3903   return true;
   3904 }
   3905 
   3906 
   3907 void HGraph::CollectPhis() {
   3908   int block_count = blocks_.length();
   3909   phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
   3910   for (int i = 0; i < block_count; ++i) {
   3911     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   3912       HPhi* phi = blocks_[i]->phis()->at(j);
   3913       phi_list_->Add(phi, zone());
   3914     }
   3915   }
   3916 }
   3917 
   3918 
   3919 // Implementation of utility class to encapsulate the translation state for
   3920 // a (possibly inlined) function.
   3921 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
   3922                              CompilationInfo* info,
   3923                              InliningKind inlining_kind,
   3924                              int inlining_id)
   3925     : owner_(owner),
   3926       compilation_info_(info),
   3927       call_context_(NULL),
   3928       inlining_kind_(inlining_kind),
   3929       function_return_(NULL),
   3930       test_context_(NULL),
   3931       entry_(NULL),
   3932       arguments_object_(NULL),
   3933       arguments_elements_(NULL),
   3934       inlining_id_(inlining_id),
   3935       outer_source_position_(HSourcePosition::Unknown()),
   3936       outer_(owner->function_state()) {
   3937   if (outer_ != NULL) {
   3938     // State for an inline function.
   3939     if (owner->ast_context()->IsTest()) {
   3940       HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
   3941       HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
   3942       if_true->MarkAsInlineReturnTarget(owner->current_block());
   3943       if_false->MarkAsInlineReturnTarget(owner->current_block());
   3944       TestContext* outer_test_context = TestContext::cast(owner->ast_context());
   3945       Expression* cond = outer_test_context->condition();
   3946       // The AstContext constructor pushed on the context stack.  This newed
   3947       // instance is the reason that AstContext can't be BASE_EMBEDDED.
   3948       test_context_ = new TestContext(owner, cond, if_true, if_false);
   3949     } else {
   3950       function_return_ = owner->graph()->CreateBasicBlock();
   3951       function_return()->MarkAsInlineReturnTarget(owner->current_block());
   3952     }
   3953     // Set this after possibly allocating a new TestContext above.
   3954     call_context_ = owner->ast_context();
   3955   }
   3956 
   3957   // Push on the state stack.
   3958   owner->set_function_state(this);
   3959 
   3960   if (FLAG_hydrogen_track_positions) {
   3961     outer_source_position_ = owner->source_position();
   3962     owner->EnterInlinedSource(
   3963       info->shared_info()->start_position(),
   3964       inlining_id);
   3965     owner->SetSourcePosition(info->shared_info()->start_position());
   3966   }
   3967 }
   3968 
   3969 
   3970 FunctionState::~FunctionState() {
   3971   delete test_context_;
   3972   owner_->set_function_state(outer_);
   3973 
   3974   if (FLAG_hydrogen_track_positions) {
   3975     owner_->set_source_position(outer_source_position_);
   3976     owner_->EnterInlinedSource(
   3977       outer_->compilation_info()->shared_info()->start_position(),
   3978       outer_->inlining_id());
   3979   }
   3980 }
   3981 
   3982 
   3983 // Implementation of utility classes to represent an expression's context in
   3984 // the AST.
   3985 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
   3986     : owner_(owner),
   3987       kind_(kind),
   3988       outer_(owner->ast_context()),
   3989       for_typeof_(false) {
   3990   owner->set_ast_context(this);  // Push.
   3991 #ifdef DEBUG
   3992   DCHECK(owner->environment()->frame_type() == JS_FUNCTION);
   3993   original_length_ = owner->environment()->length();
   3994 #endif
   3995 }
   3996 
   3997 
   3998 AstContext::~AstContext() {
   3999   owner_->set_ast_context(outer_);  // Pop.
   4000 }
   4001 
   4002 
   4003 EffectContext::~EffectContext() {
   4004   DCHECK(owner()->HasStackOverflow() ||
   4005          owner()->current_block() == NULL ||
   4006          (owner()->environment()->length() == original_length_ &&
   4007           owner()->environment()->frame_type() == JS_FUNCTION));
   4008 }
   4009 
   4010 
   4011 ValueContext::~ValueContext() {
   4012   DCHECK(owner()->HasStackOverflow() ||
   4013          owner()->current_block() == NULL ||
   4014          (owner()->environment()->length() == original_length_ + 1 &&
   4015           owner()->environment()->frame_type() == JS_FUNCTION));
   4016 }
   4017 
   4018 
   4019 void EffectContext::ReturnValue(HValue* value) {
   4020   // The value is simply ignored.
   4021 }
   4022 
   4023 
   4024 void ValueContext::ReturnValue(HValue* value) {
   4025   // The value is tracked in the bailout environment, and communicated
   4026   // through the environment as the result of the expression.
   4027   if (!arguments_allowed() && value->CheckFlag(HValue::kIsArguments)) {
   4028     owner()->Bailout(kBadValueContextForArgumentsValue);
   4029   }
   4030   owner()->Push(value);
   4031 }
   4032 
   4033 
   4034 void TestContext::ReturnValue(HValue* value) {
   4035   BuildBranch(value);
   4036 }
   4037 
   4038 
   4039 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   4040   DCHECK(!instr->IsControlInstruction());
   4041   owner()->AddInstruction(instr);
   4042   if (instr->HasObservableSideEffects()) {
   4043     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   4044   }
   4045 }
   4046 
   4047 
   4048 void EffectContext::ReturnControl(HControlInstruction* instr,
   4049                                   BailoutId ast_id) {
   4050   DCHECK(!instr->HasObservableSideEffects());
   4051   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
   4052   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
   4053   instr->SetSuccessorAt(0, empty_true);
   4054   instr->SetSuccessorAt(1, empty_false);
   4055   owner()->FinishCurrentBlock(instr);
   4056   HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
   4057   owner()->set_current_block(join);
   4058 }
   4059 
   4060 
   4061 void EffectContext::ReturnContinuation(HIfContinuation* continuation,
   4062                                        BailoutId ast_id) {
   4063   HBasicBlock* true_branch = NULL;
   4064   HBasicBlock* false_branch = NULL;
   4065   continuation->Continue(&true_branch, &false_branch);
   4066   if (!continuation->IsTrueReachable()) {
   4067     owner()->set_current_block(false_branch);
   4068   } else if (!continuation->IsFalseReachable()) {
   4069     owner()->set_current_block(true_branch);
   4070   } else {
   4071     HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
   4072     owner()->set_current_block(join);
   4073   }
   4074 }
   4075 
   4076 
   4077 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   4078   DCHECK(!instr->IsControlInstruction());
   4079   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
   4080     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
   4081   }
   4082   owner()->AddInstruction(instr);
   4083   owner()->Push(instr);
   4084   if (instr->HasObservableSideEffects()) {
   4085     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   4086   }
   4087 }
   4088 
   4089 
   4090 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
   4091   DCHECK(!instr->HasObservableSideEffects());
   4092   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
   4093     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
   4094   }
   4095   HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
   4096   HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
   4097   instr->SetSuccessorAt(0, materialize_true);
   4098   instr->SetSuccessorAt(1, materialize_false);
   4099   owner()->FinishCurrentBlock(instr);
   4100   owner()->set_current_block(materialize_true);
   4101   owner()->Push(owner()->graph()->GetConstantTrue());
   4102   owner()->set_current_block(materialize_false);
   4103   owner()->Push(owner()->graph()->GetConstantFalse());
   4104   HBasicBlock* join =
   4105     owner()->CreateJoin(materialize_true, materialize_false, ast_id);
   4106   owner()->set_current_block(join);
   4107 }
   4108 
   4109 
   4110 void ValueContext::ReturnContinuation(HIfContinuation* continuation,
   4111                                       BailoutId ast_id) {
   4112   HBasicBlock* materialize_true = NULL;
   4113   HBasicBlock* materialize_false = NULL;
   4114   continuation->Continue(&materialize_true, &materialize_false);
   4115   if (continuation->IsTrueReachable()) {
   4116     owner()->set_current_block(materialize_true);
   4117     owner()->Push(owner()->graph()->GetConstantTrue());
   4118     owner()->set_current_block(materialize_true);
   4119   }
   4120   if (continuation->IsFalseReachable()) {
   4121     owner()->set_current_block(materialize_false);
   4122     owner()->Push(owner()->graph()->GetConstantFalse());
   4123     owner()->set_current_block(materialize_false);
   4124   }
   4125   if (continuation->TrueAndFalseReachable()) {
   4126     HBasicBlock* join =
   4127         owner()->CreateJoin(materialize_true, materialize_false, ast_id);
   4128     owner()->set_current_block(join);
   4129   }
   4130 }
   4131 
   4132 
   4133 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   4134   DCHECK(!instr->IsControlInstruction());
   4135   HOptimizedGraphBuilder* builder = owner();
   4136   builder->AddInstruction(instr);
   4137   // We expect a simulate after every expression with side effects, though
   4138   // this one isn't actually needed (and wouldn't work if it were targeted).
   4139   if (instr->HasObservableSideEffects()) {
   4140     builder->Push(instr);
   4141     builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   4142     builder->Pop();
   4143   }
   4144   BuildBranch(instr);
   4145 }
   4146 
   4147 
   4148 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
   4149   DCHECK(!instr->HasObservableSideEffects());
   4150   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
   4151   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
   4152   instr->SetSuccessorAt(0, empty_true);
   4153   instr->SetSuccessorAt(1, empty_false);
   4154   owner()->FinishCurrentBlock(instr);
   4155   owner()->Goto(empty_true, if_true(), owner()->function_state());
   4156   owner()->Goto(empty_false, if_false(), owner()->function_state());
   4157   owner()->set_current_block(NULL);
   4158 }
   4159 
   4160 
   4161 void TestContext::ReturnContinuation(HIfContinuation* continuation,
   4162                                      BailoutId ast_id) {
   4163   HBasicBlock* true_branch = NULL;
   4164   HBasicBlock* false_branch = NULL;
   4165   continuation->Continue(&true_branch, &false_branch);
   4166   if (continuation->IsTrueReachable()) {
   4167     owner()->Goto(true_branch, if_true(), owner()->function_state());
   4168   }
   4169   if (continuation->IsFalseReachable()) {
   4170     owner()->Goto(false_branch, if_false(), owner()->function_state());
   4171   }
   4172   owner()->set_current_block(NULL);
   4173 }
   4174 
   4175 
   4176 void TestContext::BuildBranch(HValue* value) {
   4177   // We expect the graph to be in edge-split form: there is no edge that
   4178   // connects a branch node to a join node.  We conservatively ensure that
   4179   // property by always adding an empty block on the outgoing edges of this
   4180   // branch.
   4181   HOptimizedGraphBuilder* builder = owner();
   4182   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
   4183     builder->Bailout(kArgumentsObjectValueInATestContext);
   4184   }
   4185   ToBooleanStub::Types expected(condition()->to_boolean_types());
   4186   ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
   4187 }
   4188 
   4189 
   4190 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
   4191 #define CHECK_BAILOUT(call)                     \
   4192   do {                                          \
   4193     call;                                       \
   4194     if (HasStackOverflow()) return;             \
   4195   } while (false)
   4196 
   4197 
   4198 #define CHECK_ALIVE(call)                                       \
   4199   do {                                                          \
   4200     call;                                                       \
   4201     if (HasStackOverflow() || current_block() == NULL) return;  \
   4202   } while (false)
   4203 
   4204 
   4205 #define CHECK_ALIVE_OR_RETURN(call, value)                            \
   4206   do {                                                                \
   4207     call;                                                             \
   4208     if (HasStackOverflow() || current_block() == NULL) return value;  \
   4209   } while (false)
   4210 
   4211 
   4212 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
   4213   current_info()->AbortOptimization(reason);
   4214   SetStackOverflow();
   4215 }
   4216 
   4217 
   4218 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
   4219   EffectContext for_effect(this);
   4220   Visit(expr);
   4221 }
   4222 
   4223 
   4224 void HOptimizedGraphBuilder::VisitForValue(Expression* expr,
   4225                                            ArgumentsAllowedFlag flag) {
   4226   ValueContext for_value(this, flag);
   4227   Visit(expr);
   4228 }
   4229 
   4230 
   4231 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) {
   4232   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
   4233   for_value.set_for_typeof(true);
   4234   Visit(expr);
   4235 }
   4236 
   4237 
   4238 void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
   4239                                              HBasicBlock* true_block,
   4240                                              HBasicBlock* false_block) {
   4241   TestContext for_test(this, expr, true_block, false_block);
   4242   Visit(expr);
   4243 }
   4244 
   4245 
   4246 void HOptimizedGraphBuilder::VisitExpressions(
   4247     ZoneList<Expression*>* exprs) {
   4248   for (int i = 0; i < exprs->length(); ++i) {
   4249     CHECK_ALIVE(VisitForValue(exprs->at(i)));
   4250   }
   4251 }
   4252 
   4253 
   4254 bool HOptimizedGraphBuilder::BuildGraph() {
   4255   if (current_info()->function()->is_generator()) {
   4256     Bailout(kFunctionIsAGenerator);
   4257     return false;
   4258   }
   4259   Scope* scope = current_info()->scope();
   4260   if (scope->HasIllegalRedeclaration()) {
   4261     Bailout(kFunctionWithIllegalRedeclaration);
   4262     return false;
   4263   }
   4264   if (scope->calls_eval()) {
   4265     Bailout(kFunctionCallsEval);
   4266     return false;
   4267   }
   4268   SetUpScope(scope);
   4269 
   4270   // Add an edge to the body entry.  This is warty: the graph's start
   4271   // environment will be used by the Lithium translation as the initial
   4272   // environment on graph entry, but it has now been mutated by the
   4273   // Hydrogen translation of the instructions in the start block.  This
   4274   // environment uses values which have not been defined yet.  These
   4275   // Hydrogen instructions will then be replayed by the Lithium
   4276   // translation, so they cannot have an environment effect.  The edge to
   4277   // the body's entry block (along with some special logic for the start
   4278   // block in HInstruction::InsertAfter) seals the start block from
   4279   // getting unwanted instructions inserted.
   4280   //
   4281   // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
   4282   // Make the Hydrogen instructions in the initial block into Hydrogen
   4283   // values (but not instructions), present in the initial environment and
   4284   // not replayed by the Lithium translation.
   4285   HEnvironment* initial_env = environment()->CopyWithoutHistory();
   4286   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
   4287   Goto(body_entry);
   4288   body_entry->SetJoinId(BailoutId::FunctionEntry());
   4289   set_current_block(body_entry);
   4290 
   4291   // Handle implicit declaration of the function name in named function
   4292   // expressions before other declarations.
   4293   if (scope->is_function_scope() && scope->function() != NULL) {
   4294     VisitVariableDeclaration(scope->function());
   4295   }
   4296   VisitDeclarations(scope->declarations());
   4297   Add<HSimulate>(BailoutId::Declarations());
   4298 
   4299   Add<HStackCheck>(HStackCheck::kFunctionEntry);
   4300 
   4301   VisitStatements(current_info()->function()->body());
   4302   if (HasStackOverflow()) return false;
   4303 
   4304   if (current_block() != NULL) {
   4305     Add<HReturn>(graph()->GetConstantUndefined());
   4306     set_current_block(NULL);
   4307   }
   4308 
   4309   // If the checksum of the number of type info changes is the same as the
   4310   // last time this function was compiled, then this recompile is likely not
   4311   // due to missing/inadequate type feedback, but rather too aggressive
   4312   // optimization. Disable optimistic LICM in that case.
   4313   Handle<Code> unoptimized_code(current_info()->shared_info()->code());
   4314   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
   4315   Handle<TypeFeedbackInfo> type_info(
   4316       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
   4317   int checksum = type_info->own_type_change_checksum();
   4318   int composite_checksum = graph()->update_type_change_checksum(checksum);
   4319   graph()->set_use_optimistic_licm(
   4320       !type_info->matches_inlined_type_change_checksum(composite_checksum));
   4321   type_info->set_inlined_type_change_checksum(composite_checksum);
   4322 
   4323   // Perform any necessary OSR-specific cleanups or changes to the graph.
   4324   osr()->FinishGraph();
   4325 
   4326   return true;
   4327 }
   4328 
   4329 
   4330 bool HGraph::Optimize(BailoutReason* bailout_reason) {
   4331   OrderBlocks();
   4332   AssignDominators();
   4333 
   4334   // We need to create a HConstant "zero" now so that GVN will fold every
   4335   // zero-valued constant in the graph together.
   4336   // The constant is needed to make idef-based bounds check work: the pass
   4337   // evaluates relations with "zero" and that zero cannot be created after GVN.
   4338   GetConstant0();
   4339 
   4340 #ifdef DEBUG
   4341   // Do a full verify after building the graph and computing dominators.
   4342   Verify(true);
   4343 #endif
   4344 
   4345   if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
   4346     Run<HEnvironmentLivenessAnalysisPhase>();
   4347   }
   4348 
   4349   if (!CheckConstPhiUses()) {
   4350     *bailout_reason = kUnsupportedPhiUseOfConstVariable;
   4351     return false;
   4352   }
   4353   Run<HRedundantPhiEliminationPhase>();
   4354   if (!CheckArgumentsPhiUses()) {
   4355     *bailout_reason = kUnsupportedPhiUseOfArguments;
   4356     return false;
   4357   }
   4358 
   4359   // Find and mark unreachable code to simplify optimizations, especially gvn,
   4360   // where unreachable code could unnecessarily defeat LICM.
   4361   Run<HMarkUnreachableBlocksPhase>();
   4362 
   4363   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
   4364   if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
   4365 
   4366   if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
   4367 
   4368   CollectPhis();
   4369 
   4370   if (has_osr()) osr()->FinishOsrValues();
   4371 
   4372   Run<HInferRepresentationPhase>();
   4373 
   4374   // Remove HSimulate instructions that have turned out not to be needed
   4375   // after all by folding them into the following HSimulate.
   4376   // This must happen after inferring representations.
   4377   Run<HMergeRemovableSimulatesPhase>();
   4378 
   4379   Run<HMarkDeoptimizeOnUndefinedPhase>();
   4380   Run<HRepresentationChangesPhase>();
   4381 
   4382   Run<HInferTypesPhase>();
   4383 
   4384   // Must be performed before canonicalization to ensure that Canonicalize
   4385   // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
   4386   // zero.
   4387   if (FLAG_opt_safe_uint32_operations) Run<HUint32AnalysisPhase>();
   4388 
   4389   if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
   4390 
   4391   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
   4392 
   4393   if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
   4394 
   4395   if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
   4396 
   4397   Run<HRangeAnalysisPhase>();
   4398 
   4399   Run<HComputeChangeUndefinedToNaN>();
   4400 
   4401   // Eliminate redundant stack checks on backwards branches.
   4402   Run<HStackCheckEliminationPhase>();
   4403 
   4404   if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
   4405   if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
   4406   if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
   4407   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
   4408 
   4409   RestoreActualValues();
   4410 
   4411   // Find unreachable code a second time, GVN and other optimizations may have
   4412   // made blocks unreachable that were previously reachable.
   4413   Run<HMarkUnreachableBlocksPhase>();
   4414 
   4415   return true;
   4416 }
   4417 
   4418 
   4419 void HGraph::RestoreActualValues() {
   4420   HPhase phase("H_Restore actual values", this);
   4421 
   4422   for (int block_index = 0; block_index < blocks()->length(); block_index++) {
   4423     HBasicBlock* block = blocks()->at(block_index);
   4424 
   4425 #ifdef DEBUG
   4426     for (int i = 0; i < block->phis()->length(); i++) {
   4427       HPhi* phi = block->phis()->at(i);
   4428       DCHECK(phi->ActualValue() == phi);
   4429     }
   4430 #endif
   4431 
   4432     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
   4433       HInstruction* instruction = it.Current();
   4434       if (instruction->ActualValue() == instruction) continue;
   4435       if (instruction->CheckFlag(HValue::kIsDead)) {
   4436         // The instruction was marked as deleted but left in the graph
   4437         // as a control flow dependency point for subsequent
   4438         // instructions.
   4439         instruction->DeleteAndReplaceWith(instruction->ActualValue());
   4440       } else {
   4441         DCHECK(instruction->IsInformativeDefinition());
   4442         if (instruction->IsPurelyInformativeDefinition()) {
   4443           instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
   4444         } else {
   4445           instruction->ReplaceAllUsesWith(instruction->ActualValue());
   4446         }
   4447       }
   4448     }
   4449   }
   4450 }
   4451 
   4452 
   4453 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
   4454   ZoneList<HValue*> arguments(count, zone());
   4455   for (int i = 0; i < count; ++i) {
   4456     arguments.Add(Pop(), zone());
   4457   }
   4458 
   4459   HPushArguments* push_args = New<HPushArguments>();
   4460   while (!arguments.is_empty()) {
   4461     push_args->AddInput(arguments.RemoveLast());
   4462   }
   4463   AddInstruction(push_args);
   4464 }
   4465 
   4466 
   4467 template <class Instruction>
   4468 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
   4469   PushArgumentsFromEnvironment(call->argument_count());
   4470   return call;
   4471 }
   4472 
   4473 
   4474 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
   4475   // First special is HContext.
   4476   HInstruction* context = Add<HContext>();
   4477   environment()->BindContext(context);
   4478 
   4479   // Create an arguments object containing the initial parameters.  Set the
   4480   // initial values of parameters including "this" having parameter index 0.
   4481   DCHECK_EQ(scope->num_parameters() + 1, environment()->parameter_count());
   4482   HArgumentsObject* arguments_object =
   4483       New<HArgumentsObject>(environment()->parameter_count());
   4484   for (int i = 0; i < environment()->parameter_count(); ++i) {
   4485     HInstruction* parameter = Add<HParameter>(i);
   4486     arguments_object->AddArgument(parameter, zone());
   4487     environment()->Bind(i, parameter);
   4488   }
   4489   AddInstruction(arguments_object);
   4490   graph()->SetArgumentsObject(arguments_object);
   4491 
   4492   HConstant* undefined_constant = graph()->GetConstantUndefined();
   4493   // Initialize specials and locals to undefined.
   4494   for (int i = environment()->parameter_count() + 1;
   4495        i < environment()->length();
   4496        ++i) {
   4497     environment()->Bind(i, undefined_constant);
   4498   }
   4499 
   4500   // Handle the arguments and arguments shadow variables specially (they do
   4501   // not have declarations).
   4502   if (scope->arguments() != NULL) {
   4503     if (!scope->arguments()->IsStackAllocated()) {
   4504       return Bailout(kContextAllocatedArguments);
   4505     }
   4506 
   4507     environment()->Bind(scope->arguments(),
   4508                         graph()->GetArgumentsObject());
   4509   }
   4510 }
   4511 
   4512 
   4513 Type* HOptimizedGraphBuilder::ToType(Handle<Map> map) {
   4514   return IC::MapToType<Type>(map, zone());
   4515 }
   4516 
   4517 
   4518 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
   4519   for (int i = 0; i < statements->length(); i++) {
   4520     Statement* stmt = statements->at(i);
   4521     CHECK_ALIVE(Visit(stmt));
   4522     if (stmt->IsJump()) break;
   4523   }
   4524 }
   4525 
   4526 
   4527 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
   4528   DCHECK(!HasStackOverflow());
   4529   DCHECK(current_block() != NULL);
   4530   DCHECK(current_block()->HasPredecessor());
   4531 
   4532   Scope* outer_scope = scope();
   4533   Scope* scope = stmt->scope();
   4534   BreakAndContinueInfo break_info(stmt, outer_scope);
   4535 
   4536   { BreakAndContinueScope push(&break_info, this);
   4537     if (scope != NULL) {
   4538       // Load the function object.
   4539       Scope* declaration_scope = scope->DeclarationScope();
   4540       HInstruction* function;
   4541       HValue* outer_context = environment()->context();
   4542       if (declaration_scope->is_global_scope() ||
   4543           declaration_scope->is_eval_scope()) {
   4544         function = new(zone()) HLoadContextSlot(
   4545             outer_context, Context::CLOSURE_INDEX, HLoadContextSlot::kNoCheck);
   4546       } else {
   4547         function = New<HThisFunction>();
   4548       }
   4549       AddInstruction(function);
   4550       // Allocate a block context and store it to the stack frame.
   4551       HInstruction* inner_context = Add<HAllocateBlockContext>(
   4552           outer_context, function, scope->GetScopeInfo());
   4553       HInstruction* instr = Add<HStoreFrameContext>(inner_context);
   4554       if (instr->HasObservableSideEffects()) {
   4555         AddSimulate(stmt->EntryId(), REMOVABLE_SIMULATE);
   4556       }
   4557       set_scope(scope);
   4558       environment()->BindContext(inner_context);
   4559       VisitDeclarations(scope->declarations());
   4560       AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
   4561     }
   4562     CHECK_BAILOUT(VisitStatements(stmt->statements()));
   4563   }
   4564   set_scope(outer_scope);
   4565   if (scope != NULL && current_block() != NULL) {
   4566     HValue* inner_context = environment()->context();
   4567     HValue* outer_context = Add<HLoadNamedField>(
   4568         inner_context, static_cast<HValue*>(NULL),
   4569         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4570 
   4571     HInstruction* instr = Add<HStoreFrameContext>(outer_context);
   4572     if (instr->HasObservableSideEffects()) {
   4573       AddSimulate(stmt->ExitId(), REMOVABLE_SIMULATE);
   4574     }
   4575     environment()->BindContext(outer_context);
   4576   }
   4577   HBasicBlock* break_block = break_info.break_block();
   4578   if (break_block != NULL) {
   4579     if (current_block() != NULL) Goto(break_block);
   4580     break_block->SetJoinId(stmt->ExitId());
   4581     set_current_block(break_block);
   4582   }
   4583 }
   4584 
   4585 
   4586 void HOptimizedGraphBuilder::VisitExpressionStatement(
   4587     ExpressionStatement* stmt) {
   4588   DCHECK(!HasStackOverflow());
   4589   DCHECK(current_block() != NULL);
   4590   DCHECK(current_block()->HasPredecessor());
   4591   VisitForEffect(stmt->expression());
   4592 }
   4593 
   4594 
   4595 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
   4596   DCHECK(!HasStackOverflow());
   4597   DCHECK(current_block() != NULL);
   4598   DCHECK(current_block()->HasPredecessor());
   4599 }
   4600 
   4601 
   4602 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
   4603   DCHECK(!HasStackOverflow());
   4604   DCHECK(current_block() != NULL);
   4605   DCHECK(current_block()->HasPredecessor());
   4606   if (stmt->condition()->ToBooleanIsTrue()) {
   4607     Add<HSimulate>(stmt->ThenId());
   4608     Visit(stmt->then_statement());
   4609   } else if (stmt->condition()->ToBooleanIsFalse()) {
   4610     Add<HSimulate>(stmt->ElseId());
   4611     Visit(stmt->else_statement());
   4612   } else {
   4613     HBasicBlock* cond_true = graph()->CreateBasicBlock();
   4614     HBasicBlock* cond_false = graph()->CreateBasicBlock();
   4615     CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
   4616 
   4617     if (cond_true->HasPredecessor()) {
   4618       cond_true->SetJoinId(stmt->ThenId());
   4619       set_current_block(cond_true);
   4620       CHECK_BAILOUT(Visit(stmt->then_statement()));
   4621       cond_true = current_block();
   4622     } else {
   4623       cond_true = NULL;
   4624     }
   4625 
   4626     if (cond_false->HasPredecessor()) {
   4627       cond_false->SetJoinId(stmt->ElseId());
   4628       set_current_block(cond_false);
   4629       CHECK_BAILOUT(Visit(stmt->else_statement()));
   4630       cond_false = current_block();
   4631     } else {
   4632       cond_false = NULL;
   4633     }
   4634 
   4635     HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
   4636     set_current_block(join);
   4637   }
   4638 }
   4639 
   4640 
   4641 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
   4642     BreakableStatement* stmt,
   4643     BreakType type,
   4644     Scope** scope,
   4645     int* drop_extra) {
   4646   *drop_extra = 0;
   4647   BreakAndContinueScope* current = this;
   4648   while (current != NULL && current->info()->target() != stmt) {
   4649     *drop_extra += current->info()->drop_extra();
   4650     current = current->next();
   4651   }
   4652   DCHECK(current != NULL);  // Always found (unless stack is malformed).
   4653   *scope = current->info()->scope();
   4654 
   4655   if (type == BREAK) {
   4656     *drop_extra += current->info()->drop_extra();
   4657   }
   4658 
   4659   HBasicBlock* block = NULL;
   4660   switch (type) {
   4661     case BREAK:
   4662       block = current->info()->break_block();
   4663       if (block == NULL) {
   4664         block = current->owner()->graph()->CreateBasicBlock();
   4665         current->info()->set_break_block(block);
   4666       }
   4667       break;
   4668 
   4669     case CONTINUE:
   4670       block = current->info()->continue_block();
   4671       if (block == NULL) {
   4672         block = current->owner()->graph()->CreateBasicBlock();
   4673         current->info()->set_continue_block(block);
   4674       }
   4675       break;
   4676   }
   4677 
   4678   return block;
   4679 }
   4680 
   4681 
   4682 void HOptimizedGraphBuilder::VisitContinueStatement(
   4683     ContinueStatement* stmt) {
   4684   DCHECK(!HasStackOverflow());
   4685   DCHECK(current_block() != NULL);
   4686   DCHECK(current_block()->HasPredecessor());
   4687   Scope* outer_scope = NULL;
   4688   Scope* inner_scope = scope();
   4689   int drop_extra = 0;
   4690   HBasicBlock* continue_block = break_scope()->Get(
   4691       stmt->target(), BreakAndContinueScope::CONTINUE,
   4692       &outer_scope, &drop_extra);
   4693   HValue* context = environment()->context();
   4694   Drop(drop_extra);
   4695   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
   4696   if (context_pop_count > 0) {
   4697     while (context_pop_count-- > 0) {
   4698       HInstruction* context_instruction = Add<HLoadNamedField>(
   4699           context, static_cast<HValue*>(NULL),
   4700           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4701       context = context_instruction;
   4702     }
   4703     HInstruction* instr = Add<HStoreFrameContext>(context);
   4704     if (instr->HasObservableSideEffects()) {
   4705       AddSimulate(stmt->target()->EntryId(), REMOVABLE_SIMULATE);
   4706     }
   4707     environment()->BindContext(context);
   4708   }
   4709 
   4710   Goto(continue_block);
   4711   set_current_block(NULL);
   4712 }
   4713 
   4714 
   4715 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
   4716   DCHECK(!HasStackOverflow());
   4717   DCHECK(current_block() != NULL);
   4718   DCHECK(current_block()->HasPredecessor());
   4719   Scope* outer_scope = NULL;
   4720   Scope* inner_scope = scope();
   4721   int drop_extra = 0;
   4722   HBasicBlock* break_block = break_scope()->Get(
   4723       stmt->target(), BreakAndContinueScope::BREAK,
   4724       &outer_scope, &drop_extra);
   4725   HValue* context = environment()->context();
   4726   Drop(drop_extra);
   4727   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
   4728   if (context_pop_count > 0) {
   4729     while (context_pop_count-- > 0) {
   4730       HInstruction* context_instruction = Add<HLoadNamedField>(
   4731           context, static_cast<HValue*>(NULL),
   4732           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4733       context = context_instruction;
   4734     }
   4735     HInstruction* instr = Add<HStoreFrameContext>(context);
   4736     if (instr->HasObservableSideEffects()) {
   4737       AddSimulate(stmt->target()->ExitId(), REMOVABLE_SIMULATE);
   4738     }
   4739     environment()->BindContext(context);
   4740   }
   4741   Goto(break_block);
   4742   set_current_block(NULL);
   4743 }
   4744 
   4745 
   4746 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
   4747   DCHECK(!HasStackOverflow());
   4748   DCHECK(current_block() != NULL);
   4749   DCHECK(current_block()->HasPredecessor());
   4750   FunctionState* state = function_state();
   4751   AstContext* context = call_context();
   4752   if (context == NULL) {
   4753     // Not an inlined return, so an actual one.
   4754     CHECK_ALIVE(VisitForValue(stmt->expression()));
   4755     HValue* result = environment()->Pop();
   4756     Add<HReturn>(result);
   4757   } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
   4758     // Return from an inlined construct call. In a test context the return value
   4759     // will always evaluate to true, in a value context the return value needs
   4760     // to be a JSObject.
   4761     if (context->IsTest()) {
   4762       TestContext* test = TestContext::cast(context);
   4763       CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4764       Goto(test->if_true(), state);
   4765     } else if (context->IsEffect()) {
   4766       CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4767       Goto(function_return(), state);
   4768     } else {
   4769       DCHECK(context->IsValue());
   4770       CHECK_ALIVE(VisitForValue(stmt->expression()));
   4771       HValue* return_value = Pop();
   4772       HValue* receiver = environment()->arguments_environment()->Lookup(0);
   4773       HHasInstanceTypeAndBranch* typecheck =
   4774           New<HHasInstanceTypeAndBranch>(return_value,
   4775                                          FIRST_SPEC_OBJECT_TYPE,
   4776                                          LAST_SPEC_OBJECT_TYPE);
   4777       HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
   4778       HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
   4779       typecheck->SetSuccessorAt(0, if_spec_object);
   4780       typecheck->SetSuccessorAt(1, not_spec_object);
   4781       FinishCurrentBlock(typecheck);
   4782       AddLeaveInlined(if_spec_object, return_value, state);
   4783       AddLeaveInlined(not_spec_object, receiver, state);
   4784     }
   4785   } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
   4786     // Return from an inlined setter call. The returned value is never used, the
   4787     // value of an assignment is always the value of the RHS of the assignment.
   4788     CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4789     if (context->IsTest()) {
   4790       HValue* rhs = environment()->arguments_environment()->Lookup(1);
   4791       context->ReturnValue(rhs);
   4792     } else if (context->IsEffect()) {
   4793       Goto(function_return(), state);
   4794     } else {
   4795       DCHECK(context->IsValue());
   4796       HValue* rhs = environment()->arguments_environment()->Lookup(1);
   4797       AddLeaveInlined(rhs, state);
   4798     }
   4799   } else {
   4800     // Return from a normal inlined function. Visit the subexpression in the
   4801     // expression context of the call.
   4802     if (context->IsTest()) {
   4803       TestContext* test = TestContext::cast(context);
   4804       VisitForControl(stmt->expression(), test->if_true(), test->if_false());
   4805     } else if (context->IsEffect()) {
   4806       // Visit in value context and ignore the result. This is needed to keep
   4807       // environment in sync with full-codegen since some visitors (e.g.
   4808       // VisitCountOperation) use the operand stack differently depending on
   4809       // context.
   4810       CHECK_ALIVE(VisitForValue(stmt->expression()));
   4811       Pop();
   4812       Goto(function_return(), state);
   4813     } else {
   4814       DCHECK(context->IsValue());
   4815       CHECK_ALIVE(VisitForValue(stmt->expression()));
   4816       AddLeaveInlined(Pop(), state);
   4817     }
   4818   }
   4819   set_current_block(NULL);
   4820 }
   4821 
   4822 
   4823 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
   4824   DCHECK(!HasStackOverflow());
   4825   DCHECK(current_block() != NULL);
   4826   DCHECK(current_block()->HasPredecessor());
   4827   return Bailout(kWithStatement);
   4828 }
   4829 
   4830 
   4831 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
   4832   DCHECK(!HasStackOverflow());
   4833   DCHECK(current_block() != NULL);
   4834   DCHECK(current_block()->HasPredecessor());
   4835 
   4836   ZoneList<CaseClause*>* clauses = stmt->cases();
   4837   int clause_count = clauses->length();
   4838   ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
   4839 
   4840   CHECK_ALIVE(VisitForValue(stmt->tag()));
   4841   Add<HSimulate>(stmt->EntryId());
   4842   HValue* tag_value = Top();
   4843   Type* tag_type = stmt->tag()->bounds().lower;
   4844 
   4845   // 1. Build all the tests, with dangling true branches
   4846   BailoutId default_id = BailoutId::None();
   4847   for (int i = 0; i < clause_count; ++i) {
   4848     CaseClause* clause = clauses->at(i);
   4849     if (clause->is_default()) {
   4850       body_blocks.Add(NULL, zone());
   4851       if (default_id.IsNone()) default_id = clause->EntryId();
   4852       continue;
   4853     }
   4854 
   4855     // Generate a compare and branch.
   4856     CHECK_ALIVE(VisitForValue(clause->label()));
   4857     HValue* label_value = Pop();
   4858 
   4859     Type* label_type = clause->label()->bounds().lower;
   4860     Type* combined_type = clause->compare_type();
   4861     HControlInstruction* compare = BuildCompareInstruction(
   4862         Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
   4863         combined_type,
   4864         ScriptPositionToSourcePosition(stmt->tag()->position()),
   4865         ScriptPositionToSourcePosition(clause->label()->position()),
   4866         PUSH_BEFORE_SIMULATE, clause->id());
   4867 
   4868     HBasicBlock* next_test_block = graph()->CreateBasicBlock();
   4869     HBasicBlock* body_block = graph()->CreateBasicBlock();
   4870     body_blocks.Add(body_block, zone());
   4871     compare->SetSuccessorAt(0, body_block);
   4872     compare->SetSuccessorAt(1, next_test_block);
   4873     FinishCurrentBlock(compare);
   4874 
   4875     set_current_block(body_block);
   4876     Drop(1);  // tag_value
   4877 
   4878     set_current_block(next_test_block);
   4879   }
   4880 
   4881   // Save the current block to use for the default or to join with the
   4882   // exit.
   4883   HBasicBlock* last_block = current_block();
   4884   Drop(1);  // tag_value
   4885 
   4886   // 2. Loop over the clauses and the linked list of tests in lockstep,
   4887   // translating the clause bodies.
   4888   HBasicBlock* fall_through_block = NULL;
   4889 
   4890   BreakAndContinueInfo break_info(stmt, scope());
   4891   { BreakAndContinueScope push(&break_info, this);
   4892     for (int i = 0; i < clause_count; ++i) {
   4893       CaseClause* clause = clauses->at(i);
   4894 
   4895       // Identify the block where normal (non-fall-through) control flow
   4896       // goes to.
   4897       HBasicBlock* normal_block = NULL;
   4898       if (clause->is_default()) {
   4899         if (last_block == NULL) continue;
   4900         normal_block = last_block;
   4901         last_block = NULL;  // Cleared to indicate we've handled it.
   4902       } else {
   4903         normal_block = body_blocks[i];
   4904       }
   4905 
   4906       if (fall_through_block == NULL) {
   4907         set_current_block(normal_block);
   4908       } else {
   4909         HBasicBlock* join = CreateJoin(fall_through_block,
   4910                                        normal_block,
   4911                                        clause->EntryId());
   4912         set_current_block(join);
   4913       }
   4914 
   4915       CHECK_BAILOUT(VisitStatements(clause->statements()));
   4916       fall_through_block = current_block();
   4917     }
   4918   }
   4919 
   4920   // Create an up-to-3-way join.  Use the break block if it exists since
   4921   // it's already a join block.
   4922   HBasicBlock* break_block = break_info.break_block();
   4923   if (break_block == NULL) {
   4924     set_current_block(CreateJoin(fall_through_block,
   4925                                  last_block,
   4926                                  stmt->ExitId()));
   4927   } else {
   4928     if (fall_through_block != NULL) Goto(fall_through_block, break_block);
   4929     if (last_block != NULL) Goto(last_block, break_block);
   4930     break_block->SetJoinId(stmt->ExitId());
   4931     set_current_block(break_block);
   4932   }
   4933 }
   4934 
   4935 
   4936 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
   4937                                            HBasicBlock* loop_entry) {
   4938   Add<HSimulate>(stmt->StackCheckId());
   4939   HStackCheck* stack_check =
   4940       HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
   4941   DCHECK(loop_entry->IsLoopHeader());
   4942   loop_entry->loop_information()->set_stack_check(stack_check);
   4943   CHECK_BAILOUT(Visit(stmt->body()));
   4944 }
   4945 
   4946 
   4947 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
   4948   DCHECK(!HasStackOverflow());
   4949   DCHECK(current_block() != NULL);
   4950   DCHECK(current_block()->HasPredecessor());
   4951   DCHECK(current_block() != NULL);
   4952   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   4953 
   4954   BreakAndContinueInfo break_info(stmt, scope());
   4955   {
   4956     BreakAndContinueScope push(&break_info, this);
   4957     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
   4958   }
   4959   HBasicBlock* body_exit =
   4960       JoinContinue(stmt, current_block(), break_info.continue_block());
   4961   HBasicBlock* loop_successor = NULL;
   4962   if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
   4963     set_current_block(body_exit);
   4964     loop_successor = graph()->CreateBasicBlock();
   4965     if (stmt->cond()->ToBooleanIsFalse()) {
   4966       loop_entry->loop_information()->stack_check()->Eliminate();
   4967       Goto(loop_successor);
   4968       body_exit = NULL;
   4969     } else {
   4970       // The block for a true condition, the actual predecessor block of the
   4971       // back edge.
   4972       body_exit = graph()->CreateBasicBlock();
   4973       CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
   4974     }
   4975     if (body_exit != NULL && body_exit->HasPredecessor()) {
   4976       body_exit->SetJoinId(stmt->BackEdgeId());
   4977     } else {
   4978       body_exit = NULL;
   4979     }
   4980     if (loop_successor->HasPredecessor()) {
   4981       loop_successor->SetJoinId(stmt->ExitId());
   4982     } else {
   4983       loop_successor = NULL;
   4984     }
   4985   }
   4986   HBasicBlock* loop_exit = CreateLoop(stmt,
   4987                                       loop_entry,
   4988                                       body_exit,
   4989                                       loop_successor,
   4990                                       break_info.break_block());
   4991   set_current_block(loop_exit);
   4992 }
   4993 
   4994 
   4995 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
   4996   DCHECK(!HasStackOverflow());
   4997   DCHECK(current_block() != NULL);
   4998   DCHECK(current_block()->HasPredecessor());
   4999   DCHECK(current_block() != NULL);
   5000   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   5001 
   5002   // If the condition is constant true, do not generate a branch.
   5003   HBasicBlock* loop_successor = NULL;
   5004   if (!stmt->cond()->ToBooleanIsTrue()) {
   5005     HBasicBlock* body_entry = graph()->CreateBasicBlock();
   5006     loop_successor = graph()->CreateBasicBlock();
   5007     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
   5008     if (body_entry->HasPredecessor()) {
   5009       body_entry->SetJoinId(stmt->BodyId());
   5010       set_current_block(body_entry);
   5011     }
   5012     if (loop_successor->HasPredecessor()) {
   5013       loop_successor->SetJoinId(stmt->ExitId());
   5014     } else {
   5015       loop_successor = NULL;
   5016     }
   5017   }
   5018 
   5019   BreakAndContinueInfo break_info(stmt, scope());
   5020   if (current_block() != NULL) {
   5021     BreakAndContinueScope push(&break_info, this);
   5022     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
   5023   }
   5024   HBasicBlock* body_exit =
   5025       JoinContinue(stmt, current_block(), break_info.continue_block());
   5026   HBasicBlock* loop_exit = CreateLoop(stmt,
   5027                                       loop_entry,
   5028                                       body_exit,
   5029                                       loop_successor,
   5030                                       break_info.break_block());
   5031   set_current_block(loop_exit);
   5032 }
   5033 
   5034 
   5035 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
   5036   DCHECK(!HasStackOverflow());
   5037   DCHECK(current_block() != NULL);
   5038   DCHECK(current_block()->HasPredecessor());
   5039   if (stmt->init() != NULL) {
   5040     CHECK_ALIVE(Visit(stmt->init()));
   5041   }
   5042   DCHECK(current_block() != NULL);
   5043   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   5044 
   5045   HBasicBlock* loop_successor = NULL;
   5046   if (stmt->cond() != NULL) {
   5047     HBasicBlock* body_entry = graph()->CreateBasicBlock();
   5048     loop_successor = graph()->CreateBasicBlock();
   5049     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
   5050     if (body_entry->HasPredecessor()) {
   5051       body_entry->SetJoinId(stmt->BodyId());
   5052       set_current_block(body_entry);
   5053     }
   5054     if (loop_successor->HasPredecessor()) {
   5055       loop_successor->SetJoinId(stmt->ExitId());
   5056     } else {
   5057       loop_successor = NULL;
   5058     }
   5059   }
   5060 
   5061   BreakAndContinueInfo break_info(stmt, scope());
   5062   if (current_block() != NULL) {
   5063     BreakAndContinueScope push(&break_info, this);
   5064     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
   5065   }
   5066   HBasicBlock* body_exit =
   5067       JoinContinue(stmt, current_block(), break_info.continue_block());
   5068 
   5069   if (stmt->next() != NULL && body_exit != NULL) {
   5070     set_current_block(body_exit);
   5071     CHECK_BAILOUT(Visit(stmt->next()));
   5072     body_exit = current_block();
   5073   }
   5074 
   5075   HBasicBlock* loop_exit = CreateLoop(stmt,
   5076                                       loop_entry,
   5077                                       body_exit,
   5078                                       loop_successor,
   5079                                       break_info.break_block());
   5080   set_current_block(loop_exit);
   5081 }
   5082 
   5083 
   5084 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
   5085   DCHECK(!HasStackOverflow());
   5086   DCHECK(current_block() != NULL);
   5087   DCHECK(current_block()->HasPredecessor());
   5088 
   5089   if (!FLAG_optimize_for_in) {
   5090     return Bailout(kForInStatementOptimizationIsDisabled);
   5091   }
   5092 
   5093   if (stmt->for_in_type() != ForInStatement::FAST_FOR_IN) {
   5094     return Bailout(kForInStatementIsNotFastCase);
   5095   }
   5096 
   5097   if (!stmt->each()->IsVariableProxy() ||
   5098       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
   5099     return Bailout(kForInStatementWithNonLocalEachVariable);
   5100   }
   5101 
   5102   Variable* each_var = stmt->each()->AsVariableProxy()->var();
   5103 
   5104   CHECK_ALIVE(VisitForValue(stmt->enumerable()));
   5105   HValue* enumerable = Top();  // Leave enumerable at the top.
   5106 
   5107   HInstruction* map = Add<HForInPrepareMap>(enumerable);
   5108   Add<HSimulate>(stmt->PrepareId());
   5109 
   5110   HInstruction* array = Add<HForInCacheArray>(
   5111       enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
   5112 
   5113   HInstruction* enum_length = Add<HMapEnumLength>(map);
   5114 
   5115   HInstruction* start_index = Add<HConstant>(0);
   5116 
   5117   Push(map);
   5118   Push(array);
   5119   Push(enum_length);
   5120   Push(start_index);
   5121 
   5122   HInstruction* index_cache = Add<HForInCacheArray>(
   5123       enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
   5124   HForInCacheArray::cast(array)->set_index_cache(
   5125       HForInCacheArray::cast(index_cache));
   5126 
   5127   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   5128 
   5129   HValue* index = environment()->ExpressionStackAt(0);
   5130   HValue* limit = environment()->ExpressionStackAt(1);
   5131 
   5132   // Check that we still have more keys.
   5133   HCompareNumericAndBranch* compare_index =
   5134       New<HCompareNumericAndBranch>(index, limit, Token::LT);
   5135   compare_index->set_observed_input_representation(
   5136       Representation::Smi(), Representation::Smi());
   5137 
   5138   HBasicBlock* loop_body = graph()->CreateBasicBlock();
   5139   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
   5140 
   5141   compare_index->SetSuccessorAt(0, loop_body);
   5142   compare_index->SetSuccessorAt(1, loop_successor);
   5143   FinishCurrentBlock(compare_index);
   5144 
   5145   set_current_block(loop_successor);
   5146   Drop(5);
   5147 
   5148   set_current_block(loop_body);
   5149 
   5150   HValue* key = Add<HLoadKeyed>(
   5151       environment()->ExpressionStackAt(2),  // Enum cache.
   5152       environment()->ExpressionStackAt(0),  // Iteration index.
   5153       environment()->ExpressionStackAt(0),
   5154       FAST_ELEMENTS);
   5155 
   5156   // Check if the expected map still matches that of the enumerable.
   5157   // If not just deoptimize.
   5158   Add<HCheckMapValue>(environment()->ExpressionStackAt(4),
   5159                       environment()->ExpressionStackAt(3));
   5160 
   5161   Bind(each_var, key);
   5162 
   5163   BreakAndContinueInfo break_info(stmt, scope(), 5);
   5164   {
   5165     BreakAndContinueScope push(&break_info, this);
   5166     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
   5167   }
   5168 
   5169   HBasicBlock* body_exit =
   5170       JoinContinue(stmt, current_block(), break_info.continue_block());
   5171 
   5172   if (body_exit != NULL) {
   5173     set_current_block(body_exit);
   5174 
   5175     HValue* current_index = Pop();
   5176     Push(AddUncasted<HAdd>(current_index, graph()->GetConstant1()));
   5177     body_exit = current_block();
   5178   }
   5179 
   5180   HBasicBlock* loop_exit = CreateLoop(stmt,
   5181                                       loop_entry,
   5182                                       body_exit,
   5183                                       loop_successor,
   5184                                       break_info.break_block());
   5185 
   5186   set_current_block(loop_exit);
   5187 }
   5188 
   5189 
   5190 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
   5191   DCHECK(!HasStackOverflow());
   5192   DCHECK(current_block() != NULL);
   5193   DCHECK(current_block()->HasPredecessor());
   5194   return Bailout(kForOfStatement);
   5195 }
   5196 
   5197 
   5198 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
   5199   DCHECK(!HasStackOverflow());
   5200   DCHECK(current_block() != NULL);
   5201   DCHECK(current_block()->HasPredecessor());
   5202   return Bailout(kTryCatchStatement);
   5203 }
   5204 
   5205 
   5206 void HOptimizedGraphBuilder::VisitTryFinallyStatement(
   5207     TryFinallyStatement* stmt) {
   5208   DCHECK(!HasStackOverflow());
   5209   DCHECK(current_block() != NULL);
   5210   DCHECK(current_block()->HasPredecessor());
   5211   return Bailout(kTryFinallyStatement);
   5212 }
   5213 
   5214 
   5215 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
   5216   DCHECK(!HasStackOverflow());
   5217   DCHECK(current_block() != NULL);
   5218   DCHECK(current_block()->HasPredecessor());
   5219   return Bailout(kDebuggerStatement);
   5220 }
   5221 
   5222 
   5223 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
   5224   UNREACHABLE();
   5225 }
   5226 
   5227 
   5228 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
   5229   DCHECK(!HasStackOverflow());
   5230   DCHECK(current_block() != NULL);
   5231   DCHECK(current_block()->HasPredecessor());
   5232   Handle<SharedFunctionInfo> shared_info = expr->shared_info();
   5233   if (shared_info.is_null()) {
   5234     shared_info =
   5235         Compiler::BuildFunctionInfo(expr, current_info()->script(), top_info());
   5236   }
   5237   // We also have a stack overflow if the recursive compilation did.
   5238   if (HasStackOverflow()) return;
   5239   HFunctionLiteral* instr =
   5240       New<HFunctionLiteral>(shared_info, expr->pretenure());
   5241   return ast_context()->ReturnInstruction(instr, expr->id());
   5242 }
   5243 
   5244 
   5245 void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
   5246   DCHECK(!HasStackOverflow());
   5247   DCHECK(current_block() != NULL);
   5248   DCHECK(current_block()->HasPredecessor());
   5249   return Bailout(kClassLiteral);
   5250 }
   5251 
   5252 
   5253 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
   5254     NativeFunctionLiteral* expr) {
   5255   DCHECK(!HasStackOverflow());
   5256   DCHECK(current_block() != NULL);
   5257   DCHECK(current_block()->HasPredecessor());
   5258   return Bailout(kNativeFunctionLiteral);
   5259 }
   5260 
   5261 
   5262 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
   5263   DCHECK(!HasStackOverflow());
   5264   DCHECK(current_block() != NULL);
   5265   DCHECK(current_block()->HasPredecessor());
   5266   HBasicBlock* cond_true = graph()->CreateBasicBlock();
   5267   HBasicBlock* cond_false = graph()->CreateBasicBlock();
   5268   CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
   5269 
   5270   // Visit the true and false subexpressions in the same AST context as the
   5271   // whole expression.
   5272   if (cond_true->HasPredecessor()) {
   5273     cond_true->SetJoinId(expr->ThenId());
   5274     set_current_block(cond_true);
   5275     CHECK_BAILOUT(Visit(expr->then_expression()));
   5276     cond_true = current_block();
   5277   } else {
   5278     cond_true = NULL;
   5279   }
   5280 
   5281   if (cond_false->HasPredecessor()) {
   5282     cond_false->SetJoinId(expr->ElseId());
   5283     set_current_block(cond_false);
   5284     CHECK_BAILOUT(Visit(expr->else_expression()));
   5285     cond_false = current_block();
   5286   } else {
   5287     cond_false = NULL;
   5288   }
   5289 
   5290   if (!ast_context()->IsTest()) {
   5291     HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
   5292     set_current_block(join);
   5293     if (join != NULL && !ast_context()->IsEffect()) {
   5294       return ast_context()->ReturnValue(Pop());
   5295     }
   5296   }
   5297 }
   5298 
   5299 
   5300 HOptimizedGraphBuilder::GlobalPropertyAccess
   5301 HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it,
   5302                                              PropertyAccessType access_type) {
   5303   if (var->is_this() || !current_info()->has_global_object()) {
   5304     return kUseGeneric;
   5305   }
   5306 
   5307   switch (it->state()) {
   5308     case LookupIterator::ACCESSOR:
   5309     case LookupIterator::ACCESS_CHECK:
   5310     case LookupIterator::INTERCEPTOR:
   5311     case LookupIterator::NOT_FOUND:
   5312       return kUseGeneric;
   5313     case LookupIterator::DATA:
   5314       if (access_type == STORE && it->IsReadOnly()) return kUseGeneric;
   5315       return kUseCell;
   5316     case LookupIterator::JSPROXY:
   5317     case LookupIterator::TRANSITION:
   5318       UNREACHABLE();
   5319   }
   5320   UNREACHABLE();
   5321   return kUseGeneric;
   5322 }
   5323 
   5324 
   5325 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
   5326   DCHECK(var->IsContextSlot());
   5327   HValue* context = environment()->context();
   5328   int length = scope()->ContextChainLength(var->scope());
   5329   while (length-- > 0) {
   5330     context = Add<HLoadNamedField>(
   5331         context, static_cast<HValue*>(NULL),
   5332         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   5333   }
   5334   return context;
   5335 }
   5336 
   5337 
   5338 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
   5339   if (expr->is_this()) {
   5340     current_info()->set_this_has_uses(true);
   5341   }
   5342 
   5343   DCHECK(!HasStackOverflow());
   5344   DCHECK(current_block() != NULL);
   5345   DCHECK(current_block()->HasPredecessor());
   5346   Variable* variable = expr->var();
   5347   switch (variable->location()) {
   5348     case Variable::UNALLOCATED: {
   5349       if (IsLexicalVariableMode(variable->mode())) {
   5350         // TODO(rossberg): should this be an DCHECK?
   5351         return Bailout(kReferenceToGlobalLexicalVariable);
   5352       }
   5353       // Handle known global constants like 'undefined' specially to avoid a
   5354       // load from a global cell for them.
   5355       Handle<Object> constant_value =
   5356           isolate()->factory()->GlobalConstantFor(variable->name());
   5357       if (!constant_value.is_null()) {
   5358         HConstant* instr = New<HConstant>(constant_value);
   5359         return ast_context()->ReturnInstruction(instr, expr->id());
   5360       }
   5361 
   5362       Handle<GlobalObject> global(current_info()->global_object());
   5363       LookupIterator it(global, variable->name(),
   5364                         LookupIterator::OWN_SKIP_INTERCEPTOR);
   5365       GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD);
   5366 
   5367       if (type == kUseCell) {
   5368         Handle<PropertyCell> cell = it.GetPropertyCell();
   5369         if (cell->type()->IsConstant()) {
   5370           PropertyCell::AddDependentCompilationInfo(cell, top_info());
   5371           Handle<Object> constant_object = cell->type()->AsConstant()->Value();
   5372           if (constant_object->IsConsString()) {
   5373             constant_object =
   5374                 String::Flatten(Handle<String>::cast(constant_object));
   5375           }
   5376           HConstant* constant = New<HConstant>(constant_object);
   5377           return ast_context()->ReturnInstruction(constant, expr->id());
   5378         } else {
   5379           HLoadGlobalCell* instr =
   5380               New<HLoadGlobalCell>(cell, it.property_details());
   5381           return ast_context()->ReturnInstruction(instr, expr->id());
   5382         }
   5383       } else {
   5384         HValue* global_object = Add<HLoadNamedField>(
   5385             context(), static_cast<HValue*>(NULL),
   5386             HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
   5387         HLoadGlobalGeneric* instr =
   5388             New<HLoadGlobalGeneric>(global_object,
   5389                                     variable->name(),
   5390                                     ast_context()->is_for_typeof());
   5391         if (FLAG_vector_ics) {
   5392           Handle<SharedFunctionInfo> current_shared =
   5393               function_state()->compilation_info()->shared_info();
   5394           instr->SetVectorAndSlot(
   5395               handle(current_shared->feedback_vector(), isolate()),
   5396               expr->VariableFeedbackSlot());
   5397         }
   5398         return ast_context()->ReturnInstruction(instr, expr->id());
   5399       }
   5400     }
   5401 
   5402     case Variable::PARAMETER:
   5403     case Variable::LOCAL: {
   5404       HValue* value = LookupAndMakeLive(variable);
   5405       if (value == graph()->GetConstantHole()) {
   5406         DCHECK(IsDeclaredVariableMode(variable->mode()) &&
   5407                variable->mode() != VAR);
   5408         return Bailout(kReferenceToUninitializedVariable);
   5409       }
   5410       return ast_context()->ReturnValue(value);
   5411     }
   5412 
   5413     case Variable::CONTEXT: {
   5414       HValue* context = BuildContextChainWalk(variable);
   5415       HLoadContextSlot::Mode mode;
   5416       switch (variable->mode()) {
   5417         case LET:
   5418         case CONST:
   5419           mode = HLoadContextSlot::kCheckDeoptimize;
   5420           break;
   5421         case CONST_LEGACY:
   5422           mode = HLoadContextSlot::kCheckReturnUndefined;
   5423           break;
   5424         default:
   5425           mode = HLoadContextSlot::kNoCheck;
   5426           break;
   5427       }
   5428       HLoadContextSlot* instr =
   5429           new(zone()) HLoadContextSlot(context, variable->index(), mode);
   5430       return ast_context()->ReturnInstruction(instr, expr->id());
   5431     }
   5432 
   5433     case Variable::LOOKUP:
   5434       return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
   5435   }
   5436 }
   5437 
   5438 
   5439 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
   5440   DCHECK(!HasStackOverflow());
   5441   DCHECK(current_block() != NULL);
   5442   DCHECK(current_block()->HasPredecessor());
   5443   HConstant* instr = New<HConstant>(expr->value());
   5444   return ast_context()->ReturnInstruction(instr, expr->id());
   5445 }
   5446 
   5447 
   5448 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
   5449   DCHECK(!HasStackOverflow());
   5450   DCHECK(current_block() != NULL);
   5451   DCHECK(current_block()->HasPredecessor());
   5452   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
   5453   Handle<FixedArray> literals(closure->literals());
   5454   HRegExpLiteral* instr = New<HRegExpLiteral>(literals,
   5455                                               expr->pattern(),
   5456                                               expr->flags(),
   5457                                               expr->literal_index());
   5458   return ast_context()->ReturnInstruction(instr, expr->id());
   5459 }
   5460 
   5461 
   5462 static bool CanInlinePropertyAccess(Type* type) {
   5463   if (type->Is(Type::NumberOrString())) return true;
   5464   if (!type->IsClass()) return false;
   5465   Handle<Map> map = type->AsClass()->Map();
   5466   return map->IsJSObjectMap() &&
   5467       !map->is_dictionary_map() &&
   5468       !map->has_named_interceptor();
   5469 }
   5470 
   5471 
   5472 // Determines whether the given array or object literal boilerplate satisfies
   5473 // all limits to be considered for fast deep-copying and computes the total
   5474 // size of all objects that are part of the graph.
   5475 static bool IsFastLiteral(Handle<JSObject> boilerplate,
   5476                           int max_depth,
   5477                           int* max_properties) {
   5478   if (boilerplate->map()->is_deprecated() &&
   5479       !JSObject::TryMigrateInstance(boilerplate)) {
   5480     return false;
   5481   }
   5482 
   5483   DCHECK(max_depth >= 0 && *max_properties >= 0);
   5484   if (max_depth == 0) return false;
   5485 
   5486   Isolate* isolate = boilerplate->GetIsolate();
   5487   Handle<FixedArrayBase> elements(boilerplate->elements());
   5488   if (elements->length() > 0 &&
   5489       elements->map() != isolate->heap()->fixed_cow_array_map()) {
   5490     if (boilerplate->HasFastObjectElements()) {
   5491       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
   5492       int length = elements->length();
   5493       for (int i = 0; i < length; i++) {
   5494         if ((*max_properties)-- == 0) return false;
   5495         Handle<Object> value(fast_elements->get(i), isolate);
   5496         if (value->IsJSObject()) {
   5497           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   5498           if (!IsFastLiteral(value_object,
   5499                              max_depth - 1,
   5500                              max_properties)) {
   5501             return false;
   5502           }
   5503         }
   5504       }
   5505     } else if (!boilerplate->HasFastDoubleElements()) {
   5506       return false;
   5507     }
   5508   }
   5509 
   5510   Handle<FixedArray> properties(boilerplate->properties());
   5511   if (properties->length() > 0) {
   5512     return false;
   5513   } else {
   5514     Handle<DescriptorArray> descriptors(
   5515         boilerplate->map()->instance_descriptors());
   5516     int limit = boilerplate->map()->NumberOfOwnDescriptors();
   5517     for (int i = 0; i < limit; i++) {
   5518       PropertyDetails details = descriptors->GetDetails(i);
   5519       if (details.type() != FIELD) continue;
   5520       int index = descriptors->GetFieldIndex(i);
   5521       if ((*max_properties)-- == 0) return false;
   5522       Handle<Object> value(boilerplate->InObjectPropertyAt(index), isolate);
   5523       if (value->IsJSObject()) {
   5524         Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   5525         if (!IsFastLiteral(value_object,
   5526                            max_depth - 1,
   5527                            max_properties)) {
   5528           return false;
   5529         }
   5530       }
   5531     }
   5532   }
   5533   return true;
   5534 }
   5535 
   5536 
   5537 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
   5538   DCHECK(!HasStackOverflow());
   5539   DCHECK(current_block() != NULL);
   5540   DCHECK(current_block()->HasPredecessor());
   5541   expr->BuildConstantProperties(isolate());
   5542   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
   5543   HInstruction* literal;
   5544 
   5545   // Check whether to use fast or slow deep-copying for boilerplate.
   5546   int max_properties = kMaxFastLiteralProperties;
   5547   Handle<Object> literals_cell(closure->literals()->get(expr->literal_index()),
   5548                                isolate());
   5549   Handle<AllocationSite> site;
   5550   Handle<JSObject> boilerplate;
   5551   if (!literals_cell->IsUndefined()) {
   5552     // Retrieve the boilerplate
   5553     site = Handle<AllocationSite>::cast(literals_cell);
   5554     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
   5555                                    isolate());
   5556   }
   5557 
   5558   if (!boilerplate.is_null() &&
   5559       IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
   5560     AllocationSiteUsageContext usage_context(isolate(), site, false);
   5561     usage_context.EnterNewScope();
   5562     literal = BuildFastLiteral(boilerplate, &usage_context);
   5563     usage_context.ExitScope(site, boilerplate);
   5564   } else {
   5565     NoObservableSideEffectsScope no_effects(this);
   5566     Handle<FixedArray> closure_literals(closure->literals(), isolate());
   5567     Handle<FixedArray> constant_properties = expr->constant_properties();
   5568     int literal_index = expr->literal_index();
   5569     int flags = expr->fast_elements()
   5570         ? ObjectLiteral::kFastElements : ObjectLiteral::kNoFlags;
   5571     flags |= expr->has_function()
   5572         ? ObjectLiteral::kHasFunction : ObjectLiteral::kNoFlags;
   5573 
   5574     Add<HPushArguments>(Add<HConstant>(closure_literals),
   5575                         Add<HConstant>(literal_index),
   5576                         Add<HConstant>(constant_properties),
   5577                         Add<HConstant>(flags));
   5578 
   5579     // TODO(mvstanton): Add a flag to turn off creation of any
   5580     // AllocationMementos for this call: we are in crankshaft and should have
   5581     // learned enough about transition behavior to stop emitting mementos.
   5582     Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
   5583     literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
   5584                                 Runtime::FunctionForId(function_id),
   5585                                 4);
   5586   }
   5587 
   5588   // The object is expected in the bailout environment during computation
   5589   // of the property values and is the value of the entire expression.
   5590   Push(literal);
   5591 
   5592   expr->CalculateEmitStore(zone());
   5593 
   5594   for (int i = 0; i < expr->properties()->length(); i++) {
   5595     ObjectLiteral::Property* property = expr->properties()->at(i);
   5596     if (property->IsCompileTimeValue()) continue;
   5597 
   5598     Literal* key = property->key();
   5599     Expression* value = property->value();
   5600 
   5601     switch (property->kind()) {
   5602       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
   5603         DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
   5604         // Fall through.
   5605       case ObjectLiteral::Property::COMPUTED:
   5606         if (key->value()->IsInternalizedString()) {
   5607           if (property->emit_store()) {
   5608             CHECK_ALIVE(VisitForValue(value));
   5609             HValue* value = Pop();
   5610             Handle<Map> map = property->GetReceiverType();
   5611             Handle<String> name = property->key()->AsPropertyName();
   5612             HInstruction* store;
   5613             if (map.is_null()) {
   5614               // If we don't know the monomorphic type, do a generic store.
   5615               CHECK_ALIVE(store = BuildNamedGeneric(
   5616                   STORE, NULL, literal, name, value));
   5617             } else {
   5618               PropertyAccessInfo info(this, STORE, ToType(map), name);
   5619               if (info.CanAccessMonomorphic()) {
   5620                 HValue* checked_literal = Add<HCheckMaps>(literal, map);
   5621                 DCHECK(!info.IsAccessor());
   5622                 store = BuildMonomorphicAccess(
   5623                     &info, literal, checked_literal, value,
   5624                     BailoutId::None(), BailoutId::None());
   5625               } else {
   5626                 CHECK_ALIVE(store = BuildNamedGeneric(
   5627                     STORE, NULL, literal, name, value));
   5628               }
   5629             }
   5630             AddInstruction(store);
   5631             if (store->HasObservableSideEffects()) {
   5632               Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
   5633             }
   5634           } else {
   5635             CHECK_ALIVE(VisitForEffect(value));
   5636           }
   5637           break;
   5638         }
   5639         // Fall through.
   5640       case ObjectLiteral::Property::PROTOTYPE:
   5641       case ObjectLiteral::Property::SETTER:
   5642       case ObjectLiteral::Property::GETTER:
   5643         return Bailout(kObjectLiteralWithComplexProperty);
   5644       default: UNREACHABLE();
   5645     }
   5646   }
   5647 
   5648   if (expr->has_function()) {
   5649     // Return the result of the transformation to fast properties
   5650     // instead of the original since this operation changes the map
   5651     // of the object. This makes sure that the original object won't
   5652     // be used by other optimized code before it is transformed
   5653     // (e.g. because of code motion).
   5654     HToFastProperties* result = Add<HToFastProperties>(Pop());
   5655     return ast_context()->ReturnValue(result);
   5656   } else {
   5657     return ast_context()->ReturnValue(Pop());
   5658   }
   5659 }
   5660 
   5661 
   5662 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
   5663   DCHECK(!HasStackOverflow());
   5664   DCHECK(current_block() != NULL);
   5665   DCHECK(current_block()->HasPredecessor());
   5666   expr->BuildConstantElements(isolate());
   5667   ZoneList<Expression*>* subexprs = expr->values();
   5668   int length = subexprs->length();
   5669   HInstruction* literal;
   5670 
   5671   Handle<AllocationSite> site;
   5672   Handle<FixedArray> literals(environment()->closure()->literals(), isolate());
   5673   bool uninitialized = false;
   5674   Handle<Object> literals_cell(literals->get(expr->literal_index()),
   5675                                isolate());
   5676   Handle<JSObject> boilerplate_object;
   5677   if (literals_cell->IsUndefined()) {
   5678     uninitialized = true;
   5679     Handle<Object> raw_boilerplate;
   5680     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   5681         isolate(), raw_boilerplate,
   5682         Runtime::CreateArrayLiteralBoilerplate(
   5683             isolate(), literals, expr->constant_elements()),
   5684         Bailout(kArrayBoilerplateCreationFailed));
   5685 
   5686     boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
   5687     AllocationSiteCreationContext creation_context(isolate());
   5688     site = creation_context.EnterNewScope();
   5689     if (JSObject::DeepWalk(boilerplate_object, &creation_context).is_null()) {
   5690       return Bailout(kArrayBoilerplateCreationFailed);
   5691     }
   5692     creation_context.ExitScope(site, boilerplate_object);
   5693     literals->set(expr->literal_index(), *site);
   5694 
   5695     if (boilerplate_object->elements()->map() ==
   5696         isolate()->heap()->fixed_cow_array_map()) {
   5697       isolate()->counters()->cow_arrays_created_runtime()->Increment();
   5698     }
   5699   } else {
   5700     DCHECK(literals_cell->IsAllocationSite());
   5701     site = Handle<AllocationSite>::cast(literals_cell);
   5702     boilerplate_object = Handle<JSObject>(
   5703         JSObject::cast(site->transition_info()), isolate());
   5704   }
   5705 
   5706   DCHECK(!boilerplate_object.is_null());
   5707   DCHECK(site->SitePointsToLiteral());
   5708 
   5709   ElementsKind boilerplate_elements_kind =
   5710       boilerplate_object->GetElementsKind();
   5711 
   5712   // Check whether to use fast or slow deep-copying for boilerplate.
   5713   int max_properties = kMaxFastLiteralProperties;
   5714   if (IsFastLiteral(boilerplate_object,
   5715                     kMaxFastLiteralDepth,
   5716                     &max_properties)) {
   5717     AllocationSiteUsageContext usage_context(isolate(), site, false);
   5718     usage_context.EnterNewScope();
   5719     literal = BuildFastLiteral(boilerplate_object, &usage_context);
   5720     usage_context.ExitScope(site, boilerplate_object);
   5721   } else {
   5722     NoObservableSideEffectsScope no_effects(this);
   5723     // Boilerplate already exists and constant elements are never accessed,
   5724     // pass an empty fixed array to the runtime function instead.
   5725     Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
   5726     int literal_index = expr->literal_index();
   5727     int flags = expr->depth() == 1
   5728         ? ArrayLiteral::kShallowElements
   5729         : ArrayLiteral::kNoFlags;
   5730     flags |= ArrayLiteral::kDisableMementos;
   5731 
   5732     Add<HPushArguments>(Add<HConstant>(literals),
   5733                         Add<HConstant>(literal_index),
   5734                         Add<HConstant>(constants),
   5735                         Add<HConstant>(flags));
   5736 
   5737     // TODO(mvstanton): Consider a flag to turn off creation of any
   5738     // AllocationMementos for this call: we are in crankshaft and should have
   5739     // learned enough about transition behavior to stop emitting mementos.
   5740     Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
   5741     literal = Add<HCallRuntime>(isolate()->factory()->empty_string(),
   5742                                 Runtime::FunctionForId(function_id),
   5743                                 4);
   5744 
   5745     // De-opt if elements kind changed from boilerplate_elements_kind.
   5746     Handle<Map> map = Handle<Map>(boilerplate_object->map(), isolate());
   5747     literal = Add<HCheckMaps>(literal, map);
   5748   }
   5749 
   5750   // The array is expected in the bailout environment during computation
   5751   // of the property values and is the value of the entire expression.
   5752   Push(literal);
   5753   // The literal index is on the stack, too.
   5754   Push(Add<HConstant>(expr->literal_index()));
   5755 
   5756   HInstruction* elements = NULL;
   5757 
   5758   for (int i = 0; i < length; i++) {
   5759     Expression* subexpr = subexprs->at(i);
   5760     // If the subexpression is a literal or a simple materialized literal it
   5761     // is already set in the cloned array.
   5762     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
   5763 
   5764     CHECK_ALIVE(VisitForValue(subexpr));
   5765     HValue* value = Pop();
   5766     if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
   5767 
   5768     elements = AddLoadElements(literal);
   5769 
   5770     HValue* key = Add<HConstant>(i);
   5771 
   5772     switch (boilerplate_elements_kind) {
   5773       case FAST_SMI_ELEMENTS:
   5774       case FAST_HOLEY_SMI_ELEMENTS:
   5775       case FAST_ELEMENTS:
   5776       case FAST_HOLEY_ELEMENTS:
   5777       case FAST_DOUBLE_ELEMENTS:
   5778       case FAST_HOLEY_DOUBLE_ELEMENTS: {
   5779         HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value,
   5780                                               boilerplate_elements_kind);
   5781         instr->SetUninitialized(uninitialized);
   5782         break;
   5783       }
   5784       default:
   5785         UNREACHABLE();
   5786         break;
   5787     }
   5788 
   5789     Add<HSimulate>(expr->GetIdForElement(i));
   5790   }
   5791 
   5792   Drop(1);  // array literal index
   5793   return ast_context()->ReturnValue(Pop());
   5794 }
   5795 
   5796 
   5797 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
   5798                                                 Handle<Map> map) {
   5799   BuildCheckHeapObject(object);
   5800   return Add<HCheckMaps>(object, map);
   5801 }
   5802 
   5803 
   5804 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
   5805     PropertyAccessInfo* info,
   5806     HValue* checked_object) {
   5807   // See if this is a load for an immutable property
   5808   if (checked_object->ActualValue()->IsConstant()) {
   5809     Handle<Object> object(
   5810         HConstant::cast(checked_object->ActualValue())->handle(isolate()));
   5811 
   5812     if (object->IsJSObject()) {
   5813       LookupIterator it(object, info->name(),
   5814                         LookupIterator::OWN_SKIP_INTERCEPTOR);
   5815       Handle<Object> value = JSObject::GetDataProperty(&it);
   5816       if (it.IsFound() && it.IsReadOnly() && !it.IsConfigurable()) {
   5817         return New<HConstant>(value);
   5818       }
   5819     }
   5820   }
   5821 
   5822   HObjectAccess access = info->access();
   5823   if (access.representation().IsDouble()) {
   5824     // Load the heap number.
   5825     checked_object = Add<HLoadNamedField>(
   5826         checked_object, static_cast<HValue*>(NULL),
   5827         access.WithRepresentation(Representation::Tagged()));
   5828     // Load the double value from it.
   5829     access = HObjectAccess::ForHeapNumberValue();
   5830   }
   5831 
   5832   SmallMapList* map_list = info->field_maps();
   5833   if (map_list->length() == 0) {
   5834     return New<HLoadNamedField>(checked_object, checked_object, access);
   5835   }
   5836 
   5837   UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
   5838   for (int i = 0; i < map_list->length(); ++i) {
   5839     maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
   5840   }
   5841   return New<HLoadNamedField>(
   5842       checked_object, checked_object, access, maps, info->field_type());
   5843 }
   5844 
   5845 
   5846 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
   5847     PropertyAccessInfo* info,
   5848     HValue* checked_object,
   5849     HValue* value) {
   5850   bool transition_to_field = info->IsTransition();
   5851   // TODO(verwaest): Move this logic into PropertyAccessInfo.
   5852   HObjectAccess field_access = info->access();
   5853 
   5854   HStoreNamedField *instr;
   5855   if (field_access.representation().IsDouble()) {
   5856     HObjectAccess heap_number_access =
   5857         field_access.WithRepresentation(Representation::Tagged());
   5858     if (transition_to_field) {
   5859       // The store requires a mutable HeapNumber to be allocated.
   5860       NoObservableSideEffectsScope no_side_effects(this);
   5861       HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
   5862 
   5863       // TODO(hpayer): Allocation site pretenuring support.
   5864       HInstruction* heap_number = Add<HAllocate>(heap_number_size,
   5865           HType::HeapObject(),
   5866           NOT_TENURED,
   5867           MUTABLE_HEAP_NUMBER_TYPE);
   5868       AddStoreMapConstant(
   5869           heap_number, isolate()->factory()->mutable_heap_number_map());
   5870       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
   5871                             value);
   5872       instr = New<HStoreNamedField>(checked_object->ActualValue(),
   5873                                     heap_number_access,
   5874                                     heap_number);
   5875     } else {
   5876       // Already holds a HeapNumber; load the box and write its value field.
   5877       HInstruction* heap_number = Add<HLoadNamedField>(
   5878           checked_object, static_cast<HValue*>(NULL), heap_number_access);
   5879       instr = New<HStoreNamedField>(heap_number,
   5880                                     HObjectAccess::ForHeapNumberValue(),
   5881                                     value, STORE_TO_INITIALIZED_ENTRY);
   5882     }
   5883   } else {
   5884     if (field_access.representation().IsHeapObject()) {
   5885       BuildCheckHeapObject(value);
   5886     }
   5887 
   5888     if (!info->field_maps()->is_empty()) {
   5889       DCHECK(field_access.representation().IsHeapObject());
   5890       value = Add<HCheckMaps>(value, info->field_maps());
   5891     }
   5892 
   5893     // This is a normal store.
   5894     instr = New<HStoreNamedField>(
   5895         checked_object->ActualValue(), field_access, value,
   5896         transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
   5897   }
   5898 
   5899   if (transition_to_field) {
   5900     Handle<Map> transition(info->transition());
   5901     DCHECK(!transition->is_deprecated());
   5902     instr->SetTransition(Add<HConstant>(transition));
   5903   }
   5904   return instr;
   5905 }
   5906 
   5907 
   5908 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
   5909     PropertyAccessInfo* info) {
   5910   if (!CanInlinePropertyAccess(type_)) return false;
   5911 
   5912   // Currently only handle Type::Number as a polymorphic case.
   5913   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
   5914   // instruction.
   5915   if (type_->Is(Type::Number())) return false;
   5916 
   5917   // Values are only compatible for monomorphic load if they all behave the same
   5918   // regarding value wrappers.
   5919   if (type_->Is(Type::NumberOrString())) {
   5920     if (!info->type_->Is(Type::NumberOrString())) return false;
   5921   } else {
   5922     if (info->type_->Is(Type::NumberOrString())) return false;
   5923   }
   5924 
   5925   if (!LookupDescriptor()) return false;
   5926 
   5927   if (!IsFound()) {
   5928     return (!info->IsFound() || info->has_holder()) &&
   5929            map()->prototype() == info->map()->prototype();
   5930   }
   5931 
   5932   // Mismatch if the other access info found the property in the prototype
   5933   // chain.
   5934   if (info->has_holder()) return false;
   5935 
   5936   if (IsAccessor()) {
   5937     return accessor_.is_identical_to(info->accessor_) &&
   5938         api_holder_.is_identical_to(info->api_holder_);
   5939   }
   5940 
   5941   if (IsConstant()) {
   5942     return constant_.is_identical_to(info->constant_);
   5943   }
   5944 
   5945   DCHECK(IsField());
   5946   if (!info->IsField()) return false;
   5947 
   5948   Representation r = access_.representation();
   5949   if (IsLoad()) {
   5950     if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
   5951   } else {
   5952     if (!info->access_.representation().IsCompatibleForStore(r)) return false;
   5953   }
   5954   if (info->access_.offset() != access_.offset()) return false;
   5955   if (info->access_.IsInobject() != access_.IsInobject()) return false;
   5956   if (IsLoad()) {
   5957     if (field_maps_.is_empty()) {
   5958       info->field_maps_.Clear();
   5959     } else if (!info->field_maps_.is_empty()) {
   5960       for (int i = 0; i < field_maps_.length(); ++i) {
   5961         info->field_maps_.AddMapIfMissing(field_maps_.at(i), info->zone());
   5962       }
   5963       info->field_maps_.Sort();
   5964     }
   5965   } else {
   5966     // We can only merge stores that agree on their field maps. The comparison
   5967     // below is safe, since we keep the field maps sorted.
   5968     if (field_maps_.length() != info->field_maps_.length()) return false;
   5969     for (int i = 0; i < field_maps_.length(); ++i) {
   5970       if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) {
   5971         return false;
   5972       }
   5973     }
   5974   }
   5975   info->GeneralizeRepresentation(r);
   5976   info->field_type_ = info->field_type_.Combine(field_type_);
   5977   return true;
   5978 }
   5979 
   5980 
   5981 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
   5982   if (!type_->IsClass()) return true;
   5983   map()->LookupDescriptor(NULL, *name_, &lookup_);
   5984   return LoadResult(map());
   5985 }
   5986 
   5987 
   5988 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
   5989   if (!IsLoad() && IsProperty() && IsReadOnly()) {
   5990     return false;
   5991   }
   5992 
   5993   if (IsField()) {
   5994     // Construct the object field access.
   5995     int index = GetLocalFieldIndexFromMap(map);
   5996     access_ = HObjectAccess::ForField(map, index, representation(), name_);
   5997 
   5998     // Load field map for heap objects.
   5999     LoadFieldMaps(map);
   6000   } else if (IsAccessor()) {
   6001     Handle<Object> accessors = GetAccessorsFromMap(map);
   6002     if (!accessors->IsAccessorPair()) return false;
   6003     Object* raw_accessor =
   6004         IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
   6005                  : Handle<AccessorPair>::cast(accessors)->setter();
   6006     if (!raw_accessor->IsJSFunction()) return false;
   6007     Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor));
   6008     if (accessor->shared()->IsApiFunction()) {
   6009       CallOptimization call_optimization(accessor);
   6010       if (call_optimization.is_simple_api_call()) {
   6011         CallOptimization::HolderLookup holder_lookup;
   6012         Handle<Map> receiver_map = this->map();
   6013         api_holder_ = call_optimization.LookupHolderOfExpectedType(
   6014             receiver_map, &holder_lookup);
   6015       }
   6016     }
   6017     accessor_ = accessor;
   6018   } else if (IsConstant()) {
   6019     constant_ = GetConstantFromMap(map);
   6020   }
   6021 
   6022   return true;
   6023 }
   6024 
   6025 
   6026 void HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
   6027     Handle<Map> map) {
   6028   // Clear any previously collected field maps/type.
   6029   field_maps_.Clear();
   6030   field_type_ = HType::Tagged();
   6031 
   6032   // Figure out the field type from the accessor map.
   6033   Handle<HeapType> field_type = GetFieldTypeFromMap(map);
   6034 
   6035   // Collect the (stable) maps from the field type.
   6036   int num_field_maps = field_type->NumClasses();
   6037   if (num_field_maps == 0) return;
   6038   DCHECK(access_.representation().IsHeapObject());
   6039   field_maps_.Reserve(num_field_maps, zone());
   6040   HeapType::Iterator<Map> it = field_type->Classes();
   6041   while (!it.Done()) {
   6042     Handle<Map> field_map = it.Current();
   6043     if (!field_map->is_stable()) {
   6044       field_maps_.Clear();
   6045       return;
   6046     }
   6047     field_maps_.Add(field_map, zone());
   6048     it.Advance();
   6049   }
   6050   field_maps_.Sort();
   6051   DCHECK_EQ(num_field_maps, field_maps_.length());
   6052 
   6053   // Determine field HType from field HeapType.
   6054   field_type_ = HType::FromType<HeapType>(field_type);
   6055   DCHECK(field_type_.IsHeapObject());
   6056 
   6057   // Add dependency on the map that introduced the field.
   6058   Map::AddDependentCompilationInfo(GetFieldOwnerFromMap(map),
   6059                                    DependentCode::kFieldTypeGroup, top_info());
   6060 }
   6061 
   6062 
   6063 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
   6064   Handle<Map> map = this->map();
   6065 
   6066   while (map->prototype()->IsJSObject()) {
   6067     holder_ = handle(JSObject::cast(map->prototype()));
   6068     if (holder_->map()->is_deprecated()) {
   6069       JSObject::TryMigrateInstance(holder_);
   6070     }
   6071     map = Handle<Map>(holder_->map());
   6072     if (!CanInlinePropertyAccess(ToType(map))) {
   6073       lookup_.NotFound();
   6074       return false;
   6075     }
   6076     map->LookupDescriptor(*holder_, *name_, &lookup_);
   6077     if (IsFound()) return LoadResult(map);
   6078   }
   6079   lookup_.NotFound();
   6080   return true;
   6081 }
   6082 
   6083 
   6084 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
   6085   if (!CanInlinePropertyAccess(type_)) return false;
   6086   if (IsJSObjectFieldAccessor()) return IsLoad();
   6087   if (this->map()->function_with_prototype() &&
   6088       !this->map()->has_non_instance_prototype() &&
   6089       name_.is_identical_to(isolate()->factory()->prototype_string())) {
   6090     return IsLoad();
   6091   }
   6092   if (!LookupDescriptor()) return false;
   6093   if (IsFound()) return IsLoad() || !IsReadOnly();
   6094   if (!LookupInPrototypes()) return false;
   6095   if (IsLoad()) return true;
   6096 
   6097   if (IsAccessor()) return true;
   6098   Handle<Map> map = this->map();
   6099   map->LookupTransition(NULL, *name_, &lookup_);
   6100   if (lookup_.IsTransitionToField() && map->unused_property_fields() > 0) {
   6101     // Construct the object field access.
   6102     int descriptor = transition()->LastAdded();
   6103     int index =
   6104         transition()->instance_descriptors()->GetFieldIndex(descriptor) -
   6105         map->inobject_properties();
   6106     PropertyDetails details =
   6107         transition()->instance_descriptors()->GetDetails(descriptor);
   6108     Representation representation = details.representation();
   6109     access_ = HObjectAccess::ForField(map, index, representation, name_);
   6110 
   6111     // Load field map for heap objects.
   6112     LoadFieldMaps(transition());
   6113     return true;
   6114   }
   6115   return false;
   6116 }
   6117 
   6118 
   6119 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
   6120     SmallMapList* types) {
   6121   DCHECK(type_->Is(ToType(types->first())));
   6122   if (!CanAccessMonomorphic()) return false;
   6123   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
   6124   if (types->length() > kMaxLoadPolymorphism) return false;
   6125 
   6126   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
   6127   if (GetJSObjectFieldAccess(&access)) {
   6128     for (int i = 1; i < types->length(); ++i) {
   6129       PropertyAccessInfo test_info(
   6130           builder_, access_type_, ToType(types->at(i)), name_);
   6131       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
   6132       if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
   6133       if (!access.Equals(test_access)) return false;
   6134     }
   6135     return true;
   6136   }
   6137 
   6138   // Currently only handle Type::Number as a polymorphic case.
   6139   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
   6140   // instruction.
   6141   if (type_->Is(Type::Number())) return false;
   6142 
   6143   // Multiple maps cannot transition to the same target map.
   6144   DCHECK(!IsLoad() || !IsTransition());
   6145   if (IsTransition() && types->length() > 1) return false;
   6146 
   6147   for (int i = 1; i < types->length(); ++i) {
   6148     PropertyAccessInfo test_info(
   6149         builder_, access_type_, ToType(types->at(i)), name_);
   6150     if (!test_info.IsCompatible(this)) return false;
   6151   }
   6152 
   6153   return true;
   6154 }
   6155 
   6156 
   6157 Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
   6158   JSFunction* ctor = IC::GetRootConstructor(
   6159       type_, current_info()->closure()->context()->native_context());
   6160   if (ctor != NULL) return handle(ctor->initial_map());
   6161   return type_->AsClass()->Map();
   6162 }
   6163 
   6164 
   6165 static bool NeedsWrappingFor(Type* type, Handle<JSFunction> target) {
   6166   return type->Is(Type::NumberOrString()) &&
   6167       target->shared()->strict_mode() == SLOPPY &&
   6168       !target->shared()->native();
   6169 }
   6170 
   6171 
   6172 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicAccess(
   6173     PropertyAccessInfo* info,
   6174     HValue* object,
   6175     HValue* checked_object,
   6176     HValue* value,
   6177     BailoutId ast_id,
   6178     BailoutId return_id,
   6179     bool can_inline_accessor) {
   6180 
   6181   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
   6182   if (info->GetJSObjectFieldAccess(&access)) {
   6183     DCHECK(info->IsLoad());
   6184     return New<HLoadNamedField>(object, checked_object, access);
   6185   }
   6186 
   6187   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
   6188       info->map()->function_with_prototype()) {
   6189     DCHECK(!info->map()->has_non_instance_prototype());
   6190     return New<HLoadFunctionPrototype>(checked_object);
   6191   }
   6192 
   6193   HValue* checked_holder = checked_object;
   6194   if (info->has_holder()) {
   6195     Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
   6196     checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
   6197   }
   6198 
   6199   if (!info->IsFound()) {
   6200     DCHECK(info->IsLoad());
   6201     return graph()->GetConstantUndefined();
   6202   }
   6203 
   6204   if (info->IsField()) {
   6205     if (info->IsLoad()) {
   6206       return BuildLoadNamedField(info, checked_holder);
   6207     } else {
   6208       return BuildStoreNamedField(info, checked_object, value);
   6209     }
   6210   }
   6211 
   6212   if (info->IsTransition()) {
   6213     DCHECK(!info->IsLoad());
   6214     return BuildStoreNamedField(info, checked_object, value);
   6215   }
   6216 
   6217   if (info->IsAccessor()) {
   6218     Push(checked_object);
   6219     int argument_count = 1;
   6220     if (!info->IsLoad()) {
   6221       argument_count = 2;
   6222       Push(value);
   6223     }
   6224 
   6225     if (NeedsWrappingFor(info->type(), info->accessor())) {
   6226       HValue* function = Add<HConstant>(info->accessor());
   6227       PushArgumentsFromEnvironment(argument_count);
   6228       return New<HCallFunction>(function, argument_count, WRAP_AND_CALL);
   6229     } else if (FLAG_inline_accessors && can_inline_accessor) {
   6230       bool success = info->IsLoad()
   6231           ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
   6232           : TryInlineSetter(
   6233               info->accessor(), info->map(), ast_id, return_id, value);
   6234       if (success || HasStackOverflow()) return NULL;
   6235     }
   6236 
   6237     PushArgumentsFromEnvironment(argument_count);
   6238     return BuildCallConstantFunction(info->accessor(), argument_count);
   6239   }
   6240 
   6241   DCHECK(info->IsConstant());
   6242   if (info->IsLoad()) {
   6243     return New<HConstant>(info->constant());
   6244   } else {
   6245     return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
   6246   }
   6247 }
   6248 
   6249 
   6250 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
   6251     PropertyAccessType access_type,
   6252     Expression* expr,
   6253     BailoutId ast_id,
   6254     BailoutId return_id,
   6255     HValue* object,
   6256     HValue* value,
   6257     SmallMapList* types,
   6258     Handle<String> name) {
   6259   // Something did not match; must use a polymorphic load.
   6260   int count = 0;
   6261   HBasicBlock* join = NULL;
   6262   HBasicBlock* number_block = NULL;
   6263   bool handled_string = false;
   6264 
   6265   bool handle_smi = false;
   6266   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
   6267   int i;
   6268   for (i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
   6269     PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
   6270     if (info.type()->Is(Type::String())) {
   6271       if (handled_string) continue;
   6272       handled_string = true;
   6273     }
   6274     if (info.CanAccessMonomorphic()) {
   6275       count++;
   6276       if (info.type()->Is(Type::Number())) {
   6277         handle_smi = true;
   6278         break;
   6279       }
   6280     }
   6281   }
   6282 
   6283   if (i < types->length()) {
   6284     count = -1;
   6285     types->Clear();
   6286   } else {
   6287     count = 0;
   6288   }
   6289   HControlInstruction* smi_check = NULL;
   6290   handled_string = false;
   6291 
   6292   for (int i = 0; i < types->length() && count < kMaxLoadPolymorphism; ++i) {
   6293     PropertyAccessInfo info(this, access_type, ToType(types->at(i)), name);
   6294     if (info.type()->Is(Type::String())) {
   6295       if (handled_string) continue;
   6296       handled_string = true;
   6297     }
   6298     if (!info.CanAccessMonomorphic()) continue;
   6299 
   6300     if (count == 0) {
   6301       join = graph()->CreateBasicBlock();
   6302       if (handle_smi) {
   6303         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
   6304         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
   6305         number_block = graph()->CreateBasicBlock();
   6306         smi_check = New<HIsSmiAndBranch>(
   6307             object, empty_smi_block, not_smi_block);
   6308         FinishCurrentBlock(smi_check);
   6309         GotoNoSimulate(empty_smi_block, number_block);
   6310         set_current_block(not_smi_block);
   6311       } else {
   6312         BuildCheckHeapObject(object);
   6313       }
   6314     }
   6315     ++count;
   6316     HBasicBlock* if_true = graph()->CreateBasicBlock();
   6317     HBasicBlock* if_false = graph()->CreateBasicBlock();
   6318     HUnaryControlInstruction* compare;
   6319 
   6320     HValue* dependency;
   6321     if (info.type()->Is(Type::Number())) {
   6322       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
   6323       compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
   6324       dependency = smi_check;
   6325     } else if (info.type()->Is(Type::String())) {
   6326       compare = New<HIsStringAndBranch>(object, if_true, if_false);
   6327       dependency = compare;
   6328     } else {
   6329       compare = New<HCompareMap>(object, info.map(), if_true, if_false);
   6330       dependency = compare;
   6331     }
   6332     FinishCurrentBlock(compare);
   6333 
   6334     if (info.type()->Is(Type::Number())) {
   6335       GotoNoSimulate(if_true, number_block);
   6336       if_true = number_block;
   6337     }
   6338 
   6339     set_current_block(if_true);
   6340 
   6341     HInstruction* access = BuildMonomorphicAccess(
   6342         &info, object, dependency, value, ast_id,
   6343         return_id, FLAG_polymorphic_inlining);
   6344 
   6345     HValue* result = NULL;
   6346     switch (access_type) {
   6347       case LOAD:
   6348         result = access;
   6349         break;
   6350       case STORE:
   6351         result = value;
   6352         break;
   6353     }
   6354 
   6355     if (access == NULL) {
   6356       if (HasStackOverflow()) return;
   6357     } else {
   6358       if (!access->IsLinked()) AddInstruction(access);
   6359       if (!ast_context()->IsEffect()) Push(result);
   6360     }
   6361 
   6362     if (current_block() != NULL) Goto(join);
   6363     set_current_block(if_false);
   6364   }
   6365 
   6366   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
   6367   // know about and do not want to handle ones we've never seen.  Otherwise
   6368   // use a generic IC.
   6369   if (count == types->length() && FLAG_deoptimize_uncommon_cases) {
   6370     FinishExitWithHardDeoptimization("Uknown map in polymorphic access");
   6371   } else {
   6372     HInstruction* instr = BuildNamedGeneric(access_type, expr, object, name,
   6373                                             value);
   6374     AddInstruction(instr);
   6375     if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
   6376 
   6377     if (join != NULL) {
   6378       Goto(join);
   6379     } else {
   6380       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6381       if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
   6382       return;
   6383     }
   6384   }
   6385 
   6386   DCHECK(join != NULL);
   6387   if (join->HasPredecessor()) {
   6388     join->SetJoinId(ast_id);
   6389     set_current_block(join);
   6390     if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
   6391   } else {
   6392     set_current_block(NULL);
   6393   }
   6394 }
   6395 
   6396 
   6397 static bool ComputeReceiverTypes(Expression* expr,
   6398                                  HValue* receiver,
   6399                                  SmallMapList** t,
   6400                                  Zone* zone) {
   6401   SmallMapList* types = expr->GetReceiverTypes();
   6402   *t = types;
   6403   bool monomorphic = expr->IsMonomorphic();
   6404   if (types != NULL && receiver->HasMonomorphicJSObjectType()) {
   6405     Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
   6406     types->FilterForPossibleTransitions(root_map);
   6407     monomorphic = types->length() == 1;
   6408   }
   6409   return monomorphic &&
   6410          CanInlinePropertyAccess(IC::MapToType<Type>(types->first(), zone));
   6411 }
   6412 
   6413 
   6414 static bool AreStringTypes(SmallMapList* types) {
   6415   for (int i = 0; i < types->length(); i++) {
   6416     if (types->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
   6417   }
   6418   return true;
   6419 }
   6420 
   6421 
   6422 void HOptimizedGraphBuilder::BuildStore(Expression* expr,
   6423                                         Property* prop,
   6424                                         BailoutId ast_id,
   6425                                         BailoutId return_id,
   6426                                         bool is_uninitialized) {
   6427   if (!prop->key()->IsPropertyName()) {
   6428     // Keyed store.
   6429     HValue* value = Pop();
   6430     HValue* key = Pop();
   6431     HValue* object = Pop();
   6432     bool has_side_effects = false;
   6433     HValue* result = HandleKeyedElementAccess(
   6434         object, key, value, expr, ast_id, return_id, STORE, &has_side_effects);
   6435     if (has_side_effects) {
   6436       if (!ast_context()->IsEffect()) Push(value);
   6437       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6438       if (!ast_context()->IsEffect()) Drop(1);
   6439     }
   6440     if (result == NULL) return;
   6441     return ast_context()->ReturnValue(value);
   6442   }
   6443 
   6444   // Named store.
   6445   HValue* value = Pop();
   6446   HValue* object = Pop();
   6447 
   6448   Literal* key = prop->key()->AsLiteral();
   6449   Handle<String> name = Handle<String>::cast(key->value());
   6450   DCHECK(!name.is_null());
   6451 
   6452   HInstruction* instr = BuildNamedAccess(STORE, ast_id, return_id, expr,
   6453                                          object, name, value, is_uninitialized);
   6454   if (instr == NULL) return;
   6455 
   6456   if (!ast_context()->IsEffect()) Push(value);
   6457   AddInstruction(instr);
   6458   if (instr->HasObservableSideEffects()) {
   6459     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6460   }
   6461   if (!ast_context()->IsEffect()) Drop(1);
   6462   return ast_context()->ReturnValue(value);
   6463 }
   6464 
   6465 
   6466 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
   6467   Property* prop = expr->target()->AsProperty();
   6468   DCHECK(prop != NULL);
   6469   CHECK_ALIVE(VisitForValue(prop->obj()));
   6470   if (!prop->key()->IsPropertyName()) {
   6471     CHECK_ALIVE(VisitForValue(prop->key()));
   6472   }
   6473   CHECK_ALIVE(VisitForValue(expr->value()));
   6474   BuildStore(expr, prop, expr->id(),
   6475              expr->AssignmentId(), expr->IsUninitialized());
   6476 }
   6477 
   6478 
   6479 // Because not every expression has a position and there is not common
   6480 // superclass of Assignment and CountOperation, we cannot just pass the
   6481 // owning expression instead of position and ast_id separately.
   6482 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
   6483     Variable* var,
   6484     HValue* value,
   6485     BailoutId ast_id) {
   6486   Handle<GlobalObject> global(current_info()->global_object());
   6487   LookupIterator it(global, var->name(), LookupIterator::OWN_SKIP_INTERCEPTOR);
   6488   GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE);
   6489   if (type == kUseCell) {
   6490     Handle<PropertyCell> cell = it.GetPropertyCell();
   6491     if (cell->type()->IsConstant()) {
   6492       Handle<Object> constant = cell->type()->AsConstant()->Value();
   6493       if (value->IsConstant()) {
   6494         HConstant* c_value = HConstant::cast(value);
   6495         if (!constant.is_identical_to(c_value->handle(isolate()))) {
   6496           Add<HDeoptimize>("Constant global variable assignment",
   6497                            Deoptimizer::EAGER);
   6498         }
   6499       } else {
   6500         HValue* c_constant = Add<HConstant>(constant);
   6501         IfBuilder builder(this);
   6502         if (constant->IsNumber()) {
   6503           builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
   6504         } else {
   6505           builder.If<HCompareObjectEqAndBranch>(value, c_constant);
   6506         }
   6507         builder.Then();
   6508         builder.Else();
   6509         Add<HDeoptimize>("Constant global variable assignment",
   6510                          Deoptimizer::EAGER);
   6511         builder.End();
   6512       }
   6513     }
   6514     HInstruction* instr =
   6515         Add<HStoreGlobalCell>(value, cell, it.property_details());
   6516     if (instr->HasObservableSideEffects()) {
   6517       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6518     }
   6519   } else {
   6520     HValue* global_object = Add<HLoadNamedField>(
   6521         context(), static_cast<HValue*>(NULL),
   6522         HObjectAccess::ForContextSlot(Context::GLOBAL_OBJECT_INDEX));
   6523     HStoreNamedGeneric* instr =
   6524         Add<HStoreNamedGeneric>(global_object, var->name(),
   6525                                  value, function_strict_mode());
   6526     USE(instr);
   6527     DCHECK(instr->HasObservableSideEffects());
   6528     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6529   }
   6530 }
   6531 
   6532 
   6533 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
   6534   Expression* target = expr->target();
   6535   VariableProxy* proxy = target->AsVariableProxy();
   6536   Property* prop = target->AsProperty();
   6537   DCHECK(proxy == NULL || prop == NULL);
   6538 
   6539   // We have a second position recorded in the FullCodeGenerator to have
   6540   // type feedback for the binary operation.
   6541   BinaryOperation* operation = expr->binary_operation();
   6542 
   6543   if (proxy != NULL) {
   6544     Variable* var = proxy->var();
   6545     if (var->mode() == LET)  {
   6546       return Bailout(kUnsupportedLetCompoundAssignment);
   6547     }
   6548 
   6549     CHECK_ALIVE(VisitForValue(operation));
   6550 
   6551     switch (var->location()) {
   6552       case Variable::UNALLOCATED:
   6553         HandleGlobalVariableAssignment(var,
   6554                                        Top(),
   6555                                        expr->AssignmentId());
   6556         break;
   6557 
   6558       case Variable::PARAMETER:
   6559       case Variable::LOCAL:
   6560         if (var->mode() == CONST_LEGACY)  {
   6561           return Bailout(kUnsupportedConstCompoundAssignment);
   6562         }
   6563         BindIfLive(var, Top());
   6564         break;
   6565 
   6566       case Variable::CONTEXT: {
   6567         // Bail out if we try to mutate a parameter value in a function
   6568         // using the arguments object.  We do not (yet) correctly handle the
   6569         // arguments property of the function.
   6570         if (current_info()->scope()->arguments() != NULL) {
   6571           // Parameters will be allocated to context slots.  We have no
   6572           // direct way to detect that the variable is a parameter so we do
   6573           // a linear search of the parameter variables.
   6574           int count = current_info()->scope()->num_parameters();
   6575           for (int i = 0; i < count; ++i) {
   6576             if (var == current_info()->scope()->parameter(i)) {
   6577               Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
   6578             }
   6579           }
   6580         }
   6581 
   6582         HStoreContextSlot::Mode mode;
   6583 
   6584         switch (var->mode()) {
   6585           case LET:
   6586             mode = HStoreContextSlot::kCheckDeoptimize;
   6587             break;
   6588           case CONST:
   6589             // This case is checked statically so no need to
   6590             // perform checks here
   6591             UNREACHABLE();
   6592           case CONST_LEGACY:
   6593             return ast_context()->ReturnValue(Pop());
   6594           default:
   6595             mode = HStoreContextSlot::kNoCheck;
   6596         }
   6597 
   6598         HValue* context = BuildContextChainWalk(var);
   6599         HStoreContextSlot* instr = Add<HStoreContextSlot>(
   6600             context, var->index(), mode, Top());
   6601         if (instr->HasObservableSideEffects()) {
   6602           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   6603         }
   6604         break;
   6605       }
   6606 
   6607       case Variable::LOOKUP:
   6608         return Bailout(kCompoundAssignmentToLookupSlot);
   6609     }
   6610     return ast_context()->ReturnValue(Pop());
   6611 
   6612   } else if (prop != NULL) {
   6613     CHECK_ALIVE(VisitForValue(prop->obj()));
   6614     HValue* object = Top();
   6615     HValue* key = NULL;
   6616     if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
   6617       CHECK_ALIVE(VisitForValue(prop->key()));
   6618       key = Top();
   6619     }
   6620 
   6621     CHECK_ALIVE(PushLoad(prop, object, key));
   6622 
   6623     CHECK_ALIVE(VisitForValue(expr->value()));
   6624     HValue* right = Pop();
   6625     HValue* left = Pop();
   6626 
   6627     Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
   6628 
   6629     BuildStore(expr, prop, expr->id(),
   6630                expr->AssignmentId(), expr->IsUninitialized());
   6631   } else {
   6632     return Bailout(kInvalidLhsInCompoundAssignment);
   6633   }
   6634 }
   6635 
   6636 
   6637 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
   6638   DCHECK(!HasStackOverflow());
   6639   DCHECK(current_block() != NULL);
   6640   DCHECK(current_block()->HasPredecessor());
   6641   VariableProxy* proxy = expr->target()->AsVariableProxy();
   6642   Property* prop = expr->target()->AsProperty();
   6643   DCHECK(proxy == NULL || prop == NULL);
   6644 
   6645   if (expr->is_compound()) {
   6646     HandleCompoundAssignment(expr);
   6647     return;
   6648   }
   6649 
   6650   if (prop != NULL) {
   6651     HandlePropertyAssignment(expr);
   6652   } else if (proxy != NULL) {
   6653     Variable* var = proxy->var();
   6654 
   6655     if (var->mode() == CONST) {
   6656       if (expr->op() != Token::INIT_CONST) {
   6657         return Bailout(kNonInitializerAssignmentToConst);
   6658       }
   6659     } else if (var->mode() == CONST_LEGACY) {
   6660       if (expr->op() != Token::INIT_CONST_LEGACY) {
   6661         CHECK_ALIVE(VisitForValue(expr->value()));
   6662         return ast_context()->ReturnValue(Pop());
   6663       }
   6664 
   6665       if (var->IsStackAllocated()) {
   6666         // We insert a use of the old value to detect unsupported uses of const
   6667         // variables (e.g. initialization inside a loop).
   6668         HValue* old_value = environment()->Lookup(var);
   6669         Add<HUseConst>(old_value);
   6670       }
   6671     }
   6672 
   6673     if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
   6674 
   6675     // Handle the assignment.
   6676     switch (var->location()) {
   6677       case Variable::UNALLOCATED:
   6678         CHECK_ALIVE(VisitForValue(expr->value()));
   6679         HandleGlobalVariableAssignment(var,
   6680                                        Top(),
   6681                                        expr->AssignmentId());
   6682         return ast_context()->ReturnValue(Pop());
   6683 
   6684       case Variable::PARAMETER:
   6685       case Variable::LOCAL: {
   6686         // Perform an initialization check for let declared variables
   6687         // or parameters.
   6688         if (var->mode() == LET && expr->op() == Token::ASSIGN) {
   6689           HValue* env_value = environment()->Lookup(var);
   6690           if (env_value == graph()->GetConstantHole()) {
   6691             return Bailout(kAssignmentToLetVariableBeforeInitialization);
   6692           }
   6693         }
   6694         // We do not allow the arguments object to occur in a context where it
   6695         // may escape, but assignments to stack-allocated locals are
   6696         // permitted.
   6697         CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
   6698         HValue* value = Pop();
   6699         BindIfLive(var, value);
   6700         return ast_context()->ReturnValue(value);
   6701       }
   6702 
   6703       case Variable::CONTEXT: {
   6704         // Bail out if we try to mutate a parameter value in a function using
   6705         // the arguments object.  We do not (yet) correctly handle the
   6706         // arguments property of the function.
   6707         if (current_info()->scope()->arguments() != NULL) {
   6708           // Parameters will rewrite to context slots.  We have no direct way
   6709           // to detect that the variable is a parameter.
   6710           int count = current_info()->scope()->num_parameters();
   6711           for (int i = 0; i < count; ++i) {
   6712             if (var == current_info()->scope()->parameter(i)) {
   6713               return Bailout(kAssignmentToParameterInArgumentsObject);
   6714             }
   6715           }
   6716         }
   6717 
   6718         CHECK_ALIVE(VisitForValue(expr->value()));
   6719         HStoreContextSlot::Mode mode;
   6720         if (expr->op() == Token::ASSIGN) {
   6721           switch (var->mode()) {
   6722             case LET:
   6723               mode = HStoreContextSlot::kCheckDeoptimize;
   6724               break;
   6725             case CONST:
   6726               // This case is checked statically so no need to
   6727               // perform checks here
   6728               UNREACHABLE();
   6729             case CONST_LEGACY:
   6730               return ast_context()->ReturnValue(Pop());
   6731             default:
   6732               mode = HStoreContextSlot::kNoCheck;
   6733           }
   6734         } else if (expr->op() == Token::INIT_VAR ||
   6735                    expr->op() == Token::INIT_LET ||
   6736                    expr->op() == Token::INIT_CONST) {
   6737           mode = HStoreContextSlot::kNoCheck;
   6738         } else {
   6739           DCHECK(expr->op() == Token::INIT_CONST_LEGACY);
   6740 
   6741           mode = HStoreContextSlot::kCheckIgnoreAssignment;
   6742         }
   6743 
   6744         HValue* context = BuildContextChainWalk(var);
   6745         HStoreContextSlot* instr = Add<HStoreContextSlot>(
   6746             context, var->index(), mode, Top());
   6747         if (instr->HasObservableSideEffects()) {
   6748           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   6749         }
   6750         return ast_context()->ReturnValue(Pop());
   6751       }
   6752 
   6753       case Variable::LOOKUP:
   6754         return Bailout(kAssignmentToLOOKUPVariable);
   6755     }
   6756   } else {
   6757     return Bailout(kInvalidLeftHandSideInAssignment);
   6758   }
   6759 }
   6760 
   6761 
   6762 void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
   6763   // Generators are not optimized, so we should never get here.
   6764   UNREACHABLE();
   6765 }
   6766 
   6767 
   6768 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
   6769   DCHECK(!HasStackOverflow());
   6770   DCHECK(current_block() != NULL);
   6771   DCHECK(current_block()->HasPredecessor());
   6772   if (!ast_context()->IsEffect()) {
   6773     // The parser turns invalid left-hand sides in assignments into throw
   6774     // statements, which may not be in effect contexts. We might still try
   6775     // to optimize such functions; bail out now if we do.
   6776     return Bailout(kInvalidLeftHandSideInAssignment);
   6777   }
   6778   CHECK_ALIVE(VisitForValue(expr->exception()));
   6779 
   6780   HValue* value = environment()->Pop();
   6781   if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
   6782   Add<HPushArguments>(value);
   6783   Add<HCallRuntime>(isolate()->factory()->empty_string(),
   6784                     Runtime::FunctionForId(Runtime::kThrow), 1);
   6785   Add<HSimulate>(expr->id());
   6786 
   6787   // If the throw definitely exits the function, we can finish with a dummy
   6788   // control flow at this point.  This is not the case if the throw is inside
   6789   // an inlined function which may be replaced.
   6790   if (call_context() == NULL) {
   6791     FinishExitCurrentBlock(New<HAbnormalExit>());
   6792   }
   6793 }
   6794 
   6795 
   6796 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
   6797   if (string->IsConstant()) {
   6798     HConstant* c_string = HConstant::cast(string);
   6799     if (c_string->HasStringValue()) {
   6800       return Add<HConstant>(c_string->StringValue()->map()->instance_type());
   6801     }
   6802   }
   6803   return Add<HLoadNamedField>(
   6804       Add<HLoadNamedField>(string, static_cast<HValue*>(NULL),
   6805                            HObjectAccess::ForMap()),
   6806       static_cast<HValue*>(NULL), HObjectAccess::ForMapInstanceType());
   6807 }
   6808 
   6809 
   6810 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
   6811   if (string->IsConstant()) {
   6812     HConstant* c_string = HConstant::cast(string);
   6813     if (c_string->HasStringValue()) {
   6814       return Add<HConstant>(c_string->StringValue()->length());
   6815     }
   6816   }
   6817   return Add<HLoadNamedField>(string, static_cast<HValue*>(NULL),
   6818                               HObjectAccess::ForStringLength());
   6819 }
   6820 
   6821 
   6822 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
   6823     PropertyAccessType access_type,
   6824     Expression* expr,
   6825     HValue* object,
   6826     Handle<String> name,
   6827     HValue* value,
   6828     bool is_uninitialized) {
   6829   if (is_uninitialized) {
   6830     Add<HDeoptimize>("Insufficient type feedback for generic named access",
   6831                      Deoptimizer::SOFT);
   6832   }
   6833   if (access_type == LOAD) {
   6834     HLoadNamedGeneric* result = New<HLoadNamedGeneric>(object, name);
   6835     if (FLAG_vector_ics) {
   6836       Handle<SharedFunctionInfo> current_shared =
   6837           function_state()->compilation_info()->shared_info();
   6838       result->SetVectorAndSlot(
   6839           handle(current_shared->feedback_vector(), isolate()),
   6840           expr->AsProperty()->PropertyFeedbackSlot());
   6841     }
   6842     return result;
   6843   } else {
   6844     return New<HStoreNamedGeneric>(object, name, value, function_strict_mode());
   6845   }
   6846 }
   6847 
   6848 
   6849 
   6850 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
   6851     PropertyAccessType access_type,
   6852     Expression* expr,
   6853     HValue* object,
   6854     HValue* key,
   6855     HValue* value) {
   6856   if (access_type == LOAD) {
   6857     HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(object, key);
   6858     if (FLAG_vector_ics) {
   6859       Handle<SharedFunctionInfo> current_shared =
   6860           function_state()->compilation_info()->shared_info();
   6861       result->SetVectorAndSlot(
   6862           handle(current_shared->feedback_vector(), isolate()),
   6863           expr->AsProperty()->PropertyFeedbackSlot());
   6864     }
   6865     return result;
   6866   } else {
   6867     return New<HStoreKeyedGeneric>(object, key, value, function_strict_mode());
   6868   }
   6869 }
   6870 
   6871 
   6872 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
   6873   // Loads from a "stock" fast holey double arrays can elide the hole check.
   6874   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
   6875   if (*map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS) &&
   6876       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
   6877     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
   6878     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
   6879     BuildCheckPrototypeMaps(prototype, object_prototype);
   6880     load_mode = ALLOW_RETURN_HOLE;
   6881     graph()->MarkDependsOnEmptyArrayProtoElements();
   6882   }
   6883 
   6884   return load_mode;
   6885 }
   6886 
   6887 
   6888 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
   6889     HValue* object,
   6890     HValue* key,
   6891     HValue* val,
   6892     HValue* dependency,
   6893     Handle<Map> map,
   6894     PropertyAccessType access_type,
   6895     KeyedAccessStoreMode store_mode) {
   6896   HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
   6897   if (dependency) {
   6898     checked_object->ClearDependsOnFlag(kElementsKind);
   6899   }
   6900 
   6901   if (access_type == STORE && map->prototype()->IsJSObject()) {
   6902     // monomorphic stores need a prototype chain check because shape
   6903     // changes could allow callbacks on elements in the chain that
   6904     // aren't compatible with monomorphic keyed stores.
   6905     PrototypeIterator iter(map);
   6906     JSObject* holder = NULL;
   6907     while (!iter.IsAtEnd()) {
   6908       holder = JSObject::cast(*PrototypeIterator::GetCurrent(iter));
   6909       iter.Advance();
   6910     }
   6911     DCHECK(holder && holder->IsJSObject());
   6912 
   6913     BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
   6914                             Handle<JSObject>(holder));
   6915   }
   6916 
   6917   LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
   6918   return BuildUncheckedMonomorphicElementAccess(
   6919       checked_object, key, val,
   6920       map->instance_type() == JS_ARRAY_TYPE,
   6921       map->elements_kind(), access_type,
   6922       load_mode, store_mode);
   6923 }
   6924 
   6925 
   6926 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
   6927     HValue* object,
   6928     HValue* key,
   6929     HValue* val,
   6930     SmallMapList* maps) {
   6931   // For polymorphic loads of similar elements kinds (i.e. all tagged or all
   6932   // double), always use the "worst case" code without a transition.  This is
   6933   // much faster than transitioning the elements to the worst case, trading a
   6934   // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
   6935   bool has_double_maps = false;
   6936   bool has_smi_or_object_maps = false;
   6937   bool has_js_array_access = false;
   6938   bool has_non_js_array_access = false;
   6939   bool has_seen_holey_elements = false;
   6940   Handle<Map> most_general_consolidated_map;
   6941   for (int i = 0; i < maps->length(); ++i) {
   6942     Handle<Map> map = maps->at(i);
   6943     if (!map->IsJSObjectMap()) return NULL;
   6944     // Don't allow mixing of JSArrays with JSObjects.
   6945     if (map->instance_type() == JS_ARRAY_TYPE) {
   6946       if (has_non_js_array_access) return NULL;
   6947       has_js_array_access = true;
   6948     } else if (has_js_array_access) {
   6949       return NULL;
   6950     } else {
   6951       has_non_js_array_access = true;
   6952     }
   6953     // Don't allow mixed, incompatible elements kinds.
   6954     if (map->has_fast_double_elements()) {
   6955       if (has_smi_or_object_maps) return NULL;
   6956       has_double_maps = true;
   6957     } else if (map->has_fast_smi_or_object_elements()) {
   6958       if (has_double_maps) return NULL;
   6959       has_smi_or_object_maps = true;
   6960     } else {
   6961       return NULL;
   6962     }
   6963     // Remember if we've ever seen holey elements.
   6964     if (IsHoleyElementsKind(map->elements_kind())) {
   6965       has_seen_holey_elements = true;
   6966     }
   6967     // Remember the most general elements kind, the code for its load will
   6968     // properly handle all of the more specific cases.
   6969     if ((i == 0) || IsMoreGeneralElementsKindTransition(
   6970             most_general_consolidated_map->elements_kind(),
   6971             map->elements_kind())) {
   6972       most_general_consolidated_map = map;
   6973     }
   6974   }
   6975   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
   6976 
   6977   HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
   6978   // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
   6979   // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
   6980   ElementsKind consolidated_elements_kind = has_seen_holey_elements
   6981       ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
   6982       : most_general_consolidated_map->elements_kind();
   6983   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
   6984       checked_object, key, val,
   6985       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
   6986       consolidated_elements_kind,
   6987       LOAD, NEVER_RETURN_HOLE, STANDARD_STORE);
   6988   return instr;
   6989 }
   6990 
   6991 
   6992 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
   6993     Expression* expr,
   6994     HValue* object,
   6995     HValue* key,
   6996     HValue* val,
   6997     SmallMapList* maps,
   6998     PropertyAccessType access_type,
   6999     KeyedAccessStoreMode store_mode,
   7000     bool* has_side_effects) {
   7001   *has_side_effects = false;
   7002   BuildCheckHeapObject(object);
   7003 
   7004   if (access_type == LOAD) {
   7005     HInstruction* consolidated_load =
   7006         TryBuildConsolidatedElementLoad(object, key, val, maps);
   7007     if (consolidated_load != NULL) {
   7008       *has_side_effects |= consolidated_load->HasObservableSideEffects();
   7009       return consolidated_load;
   7010     }
   7011   }
   7012 
   7013   // Elements_kind transition support.
   7014   MapHandleList transition_target(maps->length());
   7015   // Collect possible transition targets.
   7016   MapHandleList possible_transitioned_maps(maps->length());
   7017   for (int i = 0; i < maps->length(); ++i) {
   7018     Handle<Map> map = maps->at(i);
   7019     ElementsKind elements_kind = map->elements_kind();
   7020     if (IsFastElementsKind(elements_kind) &&
   7021         elements_kind != GetInitialFastElementsKind()) {
   7022       possible_transitioned_maps.Add(map);
   7023     }
   7024     if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) {
   7025       HInstruction* result = BuildKeyedGeneric(access_type, expr, object, key,
   7026                                                val);
   7027       *has_side_effects = result->HasObservableSideEffects();
   7028       return AddInstruction(result);
   7029     }
   7030   }
   7031   // Get transition target for each map (NULL == no transition).
   7032   for (int i = 0; i < maps->length(); ++i) {
   7033     Handle<Map> map = maps->at(i);
   7034     Handle<Map> transitioned_map =
   7035         map->FindTransitionedMap(&possible_transitioned_maps);
   7036     transition_target.Add(transitioned_map);
   7037   }
   7038 
   7039   MapHandleList untransitionable_maps(maps->length());
   7040   HTransitionElementsKind* transition = NULL;
   7041   for (int i = 0; i < maps->length(); ++i) {
   7042     Handle<Map> map = maps->at(i);
   7043     DCHECK(map->IsMap());
   7044     if (!transition_target.at(i).is_null()) {
   7045       DCHECK(Map::IsValidElementsTransition(
   7046           map->elements_kind(),
   7047           transition_target.at(i)->elements_kind()));
   7048       transition = Add<HTransitionElementsKind>(object, map,
   7049                                                 transition_target.at(i));
   7050     } else {
   7051       untransitionable_maps.Add(map);
   7052     }
   7053   }
   7054 
   7055   // If only one map is left after transitioning, handle this case
   7056   // monomorphically.
   7057   DCHECK(untransitionable_maps.length() >= 1);
   7058   if (untransitionable_maps.length() == 1) {
   7059     Handle<Map> untransitionable_map = untransitionable_maps[0];
   7060     HInstruction* instr = NULL;
   7061     if (untransitionable_map->has_slow_elements_kind() ||
   7062         !untransitionable_map->IsJSObjectMap()) {
   7063       instr = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key,
   7064                                                val));
   7065     } else {
   7066       instr = BuildMonomorphicElementAccess(
   7067           object, key, val, transition, untransitionable_map, access_type,
   7068           store_mode);
   7069     }
   7070     *has_side_effects |= instr->HasObservableSideEffects();
   7071     return access_type == STORE ? val : instr;
   7072   }
   7073 
   7074   HBasicBlock* join = graph()->CreateBasicBlock();
   7075 
   7076   for (int i = 0; i < untransitionable_maps.length(); ++i) {
   7077     Handle<Map> map = untransitionable_maps[i];
   7078     if (!map->IsJSObjectMap()) continue;
   7079     ElementsKind elements_kind = map->elements_kind();
   7080     HBasicBlock* this_map = graph()->CreateBasicBlock();
   7081     HBasicBlock* other_map = graph()->CreateBasicBlock();
   7082     HCompareMap* mapcompare =
   7083         New<HCompareMap>(object, map, this_map, other_map);
   7084     FinishCurrentBlock(mapcompare);
   7085 
   7086     set_current_block(this_map);
   7087     HInstruction* access = NULL;
   7088     if (IsDictionaryElementsKind(elements_kind)) {
   7089       access = AddInstruction(BuildKeyedGeneric(access_type, expr, object, key,
   7090                                                 val));
   7091     } else {
   7092       DCHECK(IsFastElementsKind(elements_kind) ||
   7093              IsExternalArrayElementsKind(elements_kind) ||
   7094              IsFixedTypedArrayElementsKind(elements_kind));
   7095       LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
   7096       // Happily, mapcompare is a checked object.
   7097       access = BuildUncheckedMonomorphicElementAccess(
   7098           mapcompare, key, val,
   7099           map->instance_type() == JS_ARRAY_TYPE,
   7100           elements_kind, access_type,
   7101           load_mode,
   7102           store_mode);
   7103     }
   7104     *has_side_effects |= access->HasObservableSideEffects();
   7105     // The caller will use has_side_effects and add a correct Simulate.
   7106     access->SetFlag(HValue::kHasNoObservableSideEffects);
   7107     if (access_type == LOAD) {
   7108       Push(access);
   7109     }
   7110     NoObservableSideEffectsScope scope(this);
   7111     GotoNoSimulate(join);
   7112     set_current_block(other_map);
   7113   }
   7114 
   7115   // Ensure that we visited at least one map above that goes to join. This is
   7116   // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
   7117   // rather than joining the join block. If this becomes an issue, insert a
   7118   // generic access in the case length() == 0.
   7119   DCHECK(join->predecessors()->length() > 0);
   7120   // Deopt if none of the cases matched.
   7121   NoObservableSideEffectsScope scope(this);
   7122   FinishExitWithHardDeoptimization("Unknown map in polymorphic element access");
   7123   set_current_block(join);
   7124   return access_type == STORE ? val : Pop();
   7125 }
   7126 
   7127 
   7128 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
   7129     HValue* obj, HValue* key, HValue* val, Expression* expr, BailoutId ast_id,
   7130     BailoutId return_id, PropertyAccessType access_type,
   7131     bool* has_side_effects) {
   7132   if (key->ActualValue()->IsConstant()) {
   7133     Handle<Object> constant =
   7134         HConstant::cast(key->ActualValue())->handle(isolate());
   7135     uint32_t array_index;
   7136     if (constant->IsString() &&
   7137         !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) {
   7138       if (!constant->IsUniqueName()) {
   7139         constant = isolate()->factory()->InternalizeString(
   7140             Handle<String>::cast(constant));
   7141       }
   7142       HInstruction* instr =
   7143           BuildNamedAccess(access_type, ast_id, return_id, expr, obj,
   7144                            Handle<String>::cast(constant), val, false);
   7145       if (instr == NULL || instr->IsLinked()) {
   7146         *has_side_effects = false;
   7147       } else {
   7148         AddInstruction(instr);
   7149         *has_side_effects = instr->HasObservableSideEffects();
   7150       }
   7151       return instr;
   7152     }
   7153   }
   7154 
   7155   DCHECK(!expr->IsPropertyName());
   7156   HInstruction* instr = NULL;
   7157 
   7158   SmallMapList* types;
   7159   bool monomorphic = ComputeReceiverTypes(expr, obj, &types, zone());
   7160 
   7161   bool force_generic = false;
   7162   if (access_type == STORE &&
   7163       (monomorphic || (types != NULL && !types->is_empty()))) {
   7164     // Stores can't be mono/polymorphic if their prototype chain has dictionary
   7165     // elements. However a receiver map that has dictionary elements itself
   7166     // should be left to normal mono/poly behavior (the other maps may benefit
   7167     // from highly optimized stores).
   7168     for (int i = 0; i < types->length(); i++) {
   7169       Handle<Map> current_map = types->at(i);
   7170       if (current_map->DictionaryElementsInPrototypeChainOnly()) {
   7171         force_generic = true;
   7172         monomorphic = false;
   7173         break;
   7174       }
   7175     }
   7176   }
   7177 
   7178   if (monomorphic) {
   7179     Handle<Map> map = types->first();
   7180     if (map->has_slow_elements_kind() || !map->IsJSObjectMap()) {
   7181       instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key,
   7182                                                val));
   7183     } else {
   7184       BuildCheckHeapObject(obj);
   7185       instr = BuildMonomorphicElementAccess(
   7186           obj, key, val, NULL, map, access_type, expr->GetStoreMode());
   7187     }
   7188   } else if (!force_generic && (types != NULL && !types->is_empty())) {
   7189     return HandlePolymorphicElementAccess(
   7190         expr, obj, key, val, types, access_type,
   7191         expr->GetStoreMode(), has_side_effects);
   7192   } else {
   7193     if (access_type == STORE) {
   7194       if (expr->IsAssignment() &&
   7195           expr->AsAssignment()->HasNoTypeInformation()) {
   7196         Add<HDeoptimize>("Insufficient type feedback for keyed store",
   7197                          Deoptimizer::SOFT);
   7198       }
   7199     } else {
   7200       if (expr->AsProperty()->HasNoTypeInformation()) {
   7201         Add<HDeoptimize>("Insufficient type feedback for keyed load",
   7202                          Deoptimizer::SOFT);
   7203       }
   7204     }
   7205     instr = AddInstruction(BuildKeyedGeneric(access_type, expr, obj, key, val));
   7206   }
   7207   *has_side_effects = instr->HasObservableSideEffects();
   7208   return instr;
   7209 }
   7210 
   7211 
   7212 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
   7213   // Outermost function already has arguments on the stack.
   7214   if (function_state()->outer() == NULL) return;
   7215 
   7216   if (function_state()->arguments_pushed()) return;
   7217 
   7218   // Push arguments when entering inlined function.
   7219   HEnterInlined* entry = function_state()->entry();
   7220   entry->set_arguments_pushed();
   7221 
   7222   HArgumentsObject* arguments = entry->arguments_object();
   7223   const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
   7224 
   7225   HInstruction* insert_after = entry;
   7226   for (int i = 0; i < arguments_values->length(); i++) {
   7227     HValue* argument = arguments_values->at(i);
   7228     HInstruction* push_argument = New<HPushArguments>(argument);
   7229     push_argument->InsertAfter(insert_after);
   7230     insert_after = push_argument;
   7231   }
   7232 
   7233   HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
   7234   arguments_elements->ClearFlag(HValue::kUseGVN);
   7235   arguments_elements->InsertAfter(insert_after);
   7236   function_state()->set_arguments_elements(arguments_elements);
   7237 }
   7238 
   7239 
   7240 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
   7241   VariableProxy* proxy = expr->obj()->AsVariableProxy();
   7242   if (proxy == NULL) return false;
   7243   if (!proxy->var()->IsStackAllocated()) return false;
   7244   if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
   7245     return false;
   7246   }
   7247 
   7248   HInstruction* result = NULL;
   7249   if (expr->key()->IsPropertyName()) {
   7250     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
   7251     if (!String::Equals(name, isolate()->factory()->length_string())) {
   7252       return false;
   7253     }
   7254 
   7255     if (function_state()->outer() == NULL) {
   7256       HInstruction* elements = Add<HArgumentsElements>(false);
   7257       result = New<HArgumentsLength>(elements);
   7258     } else {
   7259       // Number of arguments without receiver.
   7260       int argument_count = environment()->
   7261           arguments_environment()->parameter_count() - 1;
   7262       result = New<HConstant>(argument_count);
   7263     }
   7264   } else {
   7265     Push(graph()->GetArgumentsObject());
   7266     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
   7267     HValue* key = Pop();
   7268     Drop(1);  // Arguments object.
   7269     if (function_state()->outer() == NULL) {
   7270       HInstruction* elements = Add<HArgumentsElements>(false);
   7271       HInstruction* length = Add<HArgumentsLength>(elements);
   7272       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
   7273       result = New<HAccessArgumentsAt>(elements, length, checked_key);
   7274     } else {
   7275       EnsureArgumentsArePushedForAccess();
   7276 
   7277       // Number of arguments without receiver.
   7278       HInstruction* elements = function_state()->arguments_elements();
   7279       int argument_count = environment()->
   7280           arguments_environment()->parameter_count() - 1;
   7281       HInstruction* length = Add<HConstant>(argument_count);
   7282       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
   7283       result = New<HAccessArgumentsAt>(elements, length, checked_key);
   7284     }
   7285   }
   7286   ast_context()->ReturnInstruction(result, expr->id());
   7287   return true;
   7288 }
   7289 
   7290 
   7291 HInstruction* HOptimizedGraphBuilder::BuildNamedAccess(
   7292     PropertyAccessType access,
   7293     BailoutId ast_id,
   7294     BailoutId return_id,
   7295     Expression* expr,
   7296     HValue* object,
   7297     Handle<String> name,
   7298     HValue* value,
   7299     bool is_uninitialized) {
   7300   SmallMapList* types;
   7301   ComputeReceiverTypes(expr, object, &types, zone());
   7302   DCHECK(types != NULL);
   7303 
   7304   if (types->length() > 0) {
   7305     PropertyAccessInfo info(this, access, ToType(types->first()), name);
   7306     if (!info.CanAccessAsMonomorphic(types)) {
   7307       HandlePolymorphicNamedFieldAccess(
   7308           access, expr, ast_id, return_id, object, value, types, name);
   7309       return NULL;
   7310     }
   7311 
   7312     HValue* checked_object;
   7313     // Type::Number() is only supported by polymorphic load/call handling.
   7314     DCHECK(!info.type()->Is(Type::Number()));
   7315     BuildCheckHeapObject(object);
   7316     if (AreStringTypes(types)) {
   7317       checked_object =
   7318           Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
   7319     } else {
   7320       checked_object = Add<HCheckMaps>(object, types);
   7321     }
   7322     return BuildMonomorphicAccess(
   7323         &info, object, checked_object, value, ast_id, return_id);
   7324   }
   7325 
   7326   return BuildNamedGeneric(access, expr, object, name, value, is_uninitialized);
   7327 }
   7328 
   7329 
   7330 void HOptimizedGraphBuilder::PushLoad(Property* expr,
   7331                                       HValue* object,
   7332                                       HValue* key) {
   7333   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
   7334   Push(object);
   7335   if (key != NULL) Push(key);
   7336   BuildLoad(expr, expr->LoadId());
   7337 }
   7338 
   7339 
   7340 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
   7341                                        BailoutId ast_id) {
   7342   HInstruction* instr = NULL;
   7343   if (expr->IsStringAccess()) {
   7344     HValue* index = Pop();
   7345     HValue* string = Pop();
   7346     HInstruction* char_code = BuildStringCharCodeAt(string, index);
   7347     AddInstruction(char_code);
   7348     instr = NewUncasted<HStringCharFromCode>(char_code);
   7349 
   7350   } else if (expr->key()->IsPropertyName()) {
   7351     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
   7352     HValue* object = Pop();
   7353 
   7354     instr = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
   7355                              object, name, NULL, expr->IsUninitialized());
   7356     if (instr == NULL) return;
   7357     if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
   7358 
   7359   } else {
   7360     HValue* key = Pop();
   7361     HValue* obj = Pop();
   7362 
   7363     bool has_side_effects = false;
   7364     HValue* load = HandleKeyedElementAccess(
   7365         obj, key, NULL, expr, ast_id, expr->LoadId(), LOAD, &has_side_effects);
   7366     if (has_side_effects) {
   7367       if (ast_context()->IsEffect()) {
   7368         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   7369       } else {
   7370         Push(load);
   7371         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   7372         Drop(1);
   7373       }
   7374     }
   7375     if (load == NULL) return;
   7376     return ast_context()->ReturnValue(load);
   7377   }
   7378   return ast_context()->ReturnInstruction(instr, ast_id);
   7379 }
   7380 
   7381 
   7382 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
   7383   DCHECK(!HasStackOverflow());
   7384   DCHECK(current_block() != NULL);
   7385   DCHECK(current_block()->HasPredecessor());
   7386 
   7387   if (TryArgumentsAccess(expr)) return;
   7388 
   7389   CHECK_ALIVE(VisitForValue(expr->obj()));
   7390   if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
   7391     CHECK_ALIVE(VisitForValue(expr->key()));
   7392   }
   7393 
   7394   BuildLoad(expr, expr->id());
   7395 }
   7396 
   7397 
   7398 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) {
   7399   HCheckMaps* check = Add<HCheckMaps>(
   7400       Add<HConstant>(constant), handle(constant->map()));
   7401   check->ClearDependsOnFlag(kElementsKind);
   7402   return check;
   7403 }
   7404 
   7405 
   7406 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
   7407                                                      Handle<JSObject> holder) {
   7408   PrototypeIterator iter(isolate(), prototype,
   7409                          PrototypeIterator::START_AT_RECEIVER);
   7410   while (holder.is_null() ||
   7411          !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
   7412     BuildConstantMapCheck(
   7413         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
   7414     iter.Advance();
   7415     if (iter.IsAtEnd()) {
   7416       return NULL;
   7417     }
   7418   }
   7419   return BuildConstantMapCheck(
   7420       Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)));
   7421 }
   7422 
   7423 
   7424 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
   7425                                                    Handle<Map> receiver_map) {
   7426   if (!holder.is_null()) {
   7427     Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
   7428     BuildCheckPrototypeMaps(prototype, holder);
   7429   }
   7430 }
   7431 
   7432 
   7433 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(
   7434     HValue* fun, int argument_count, bool pass_argument_count) {
   7435   return New<HCallJSFunction>(
   7436       fun, argument_count, pass_argument_count);
   7437 }
   7438 
   7439 
   7440 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall(
   7441     HValue* fun, HValue* context,
   7442     int argument_count, HValue* expected_param_count) {
   7443   ArgumentAdaptorDescriptor descriptor(isolate());
   7444   HValue* arity = Add<HConstant>(argument_count - 1);
   7445 
   7446   HValue* op_vals[] = { context, fun, arity, expected_param_count };
   7447 
   7448   Handle<Code> adaptor =
   7449       isolate()->builtins()->ArgumentsAdaptorTrampoline();
   7450   HConstant* adaptor_value = Add<HConstant>(adaptor);
   7451 
   7452   return New<HCallWithDescriptor>(
   7453       adaptor_value, argument_count, descriptor,
   7454       Vector<HValue*>(op_vals, descriptor.GetEnvironmentLength()));
   7455 }
   7456 
   7457 
   7458 HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
   7459     Handle<JSFunction> jsfun, int argument_count) {
   7460   HValue* target = Add<HConstant>(jsfun);
   7461   // For constant functions, we try to avoid calling the
   7462   // argument adaptor and instead call the function directly
   7463   int formal_parameter_count = jsfun->shared()->formal_parameter_count();
   7464   bool dont_adapt_arguments =
   7465       (formal_parameter_count ==
   7466        SharedFunctionInfo::kDontAdaptArgumentsSentinel);
   7467   int arity = argument_count - 1;
   7468   bool can_invoke_directly =
   7469       dont_adapt_arguments || formal_parameter_count == arity;
   7470   if (can_invoke_directly) {
   7471     if (jsfun.is_identical_to(current_info()->closure())) {
   7472       graph()->MarkRecursive();
   7473     }
   7474     return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments);
   7475   } else {
   7476     HValue* param_count_value = Add<HConstant>(formal_parameter_count);
   7477     HValue* context = Add<HLoadNamedField>(
   7478         target, static_cast<HValue*>(NULL),
   7479         HObjectAccess::ForFunctionContextPointer());
   7480     return NewArgumentAdaptorCall(target, context,
   7481         argument_count, param_count_value);
   7482   }
   7483   UNREACHABLE();
   7484   return NULL;
   7485 }
   7486 
   7487 
   7488 class FunctionSorter {
   7489  public:
   7490   explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
   7491       : index_(index), ticks_(ticks), size_(size) {}
   7492 
   7493   int index() const { return index_; }
   7494   int ticks() const { return ticks_; }
   7495   int size() const { return size_; }
   7496 
   7497  private:
   7498   int index_;
   7499   int ticks_;
   7500   int size_;
   7501 };
   7502 
   7503 
   7504 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
   7505   int diff = lhs.ticks() - rhs.ticks();
   7506   if (diff != 0) return diff > 0;
   7507   return lhs.size() < rhs.size();
   7508 }
   7509 
   7510 
   7511 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(
   7512     Call* expr,
   7513     HValue* receiver,
   7514     SmallMapList* types,
   7515     Handle<String> name) {
   7516   int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
   7517   FunctionSorter order[kMaxCallPolymorphism];
   7518 
   7519   bool handle_smi = false;
   7520   bool handled_string = false;
   7521   int ordered_functions = 0;
   7522 
   7523   int i;
   7524   for (i = 0; i < types->length() && ordered_functions < kMaxCallPolymorphism;
   7525        ++i) {
   7526     PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
   7527     if (info.CanAccessMonomorphic() && info.IsConstant() &&
   7528         info.constant()->IsJSFunction()) {
   7529       if (info.type()->Is(Type::String())) {
   7530         if (handled_string) continue;
   7531         handled_string = true;
   7532       }
   7533       Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
   7534       if (info.type()->Is(Type::Number())) {
   7535         handle_smi = true;
   7536       }
   7537       expr->set_target(target);
   7538       order[ordered_functions++] = FunctionSorter(
   7539           i, target->shared()->profiler_ticks(), InliningAstSize(target));
   7540     }
   7541   }
   7542 
   7543   std::sort(order, order + ordered_functions);
   7544 
   7545   if (i < types->length()) {
   7546     types->Clear();
   7547     ordered_functions = -1;
   7548   }
   7549 
   7550   HBasicBlock* number_block = NULL;
   7551   HBasicBlock* join = NULL;
   7552   handled_string = false;
   7553   int count = 0;
   7554 
   7555   for (int fn = 0; fn < ordered_functions; ++fn) {
   7556     int i = order[fn].index();
   7557     PropertyAccessInfo info(this, LOAD, ToType(types->at(i)), name);
   7558     if (info.type()->Is(Type::String())) {
   7559       if (handled_string) continue;
   7560       handled_string = true;
   7561     }
   7562     // Reloads the target.
   7563     info.CanAccessMonomorphic();
   7564     Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
   7565 
   7566     expr->set_target(target);
   7567     if (count == 0) {
   7568       // Only needed once.
   7569       join = graph()->CreateBasicBlock();
   7570       if (handle_smi) {
   7571         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
   7572         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
   7573         number_block = graph()->CreateBasicBlock();
   7574         FinishCurrentBlock(New<HIsSmiAndBranch>(
   7575                 receiver, empty_smi_block, not_smi_block));
   7576         GotoNoSimulate(empty_smi_block, number_block);
   7577         set_current_block(not_smi_block);
   7578       } else {
   7579         BuildCheckHeapObject(receiver);
   7580       }
   7581     }
   7582     ++count;
   7583     HBasicBlock* if_true = graph()->CreateBasicBlock();
   7584     HBasicBlock* if_false = graph()->CreateBasicBlock();
   7585     HUnaryControlInstruction* compare;
   7586 
   7587     Handle<Map> map = info.map();
   7588     if (info.type()->Is(Type::Number())) {
   7589       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
   7590       compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
   7591     } else if (info.type()->Is(Type::String())) {
   7592       compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
   7593     } else {
   7594       compare = New<HCompareMap>(receiver, map, if_true, if_false);
   7595     }
   7596     FinishCurrentBlock(compare);
   7597 
   7598     if (info.type()->Is(Type::Number())) {
   7599       GotoNoSimulate(if_true, number_block);
   7600       if_true = number_block;
   7601     }
   7602 
   7603     set_current_block(if_true);
   7604 
   7605     AddCheckPrototypeMaps(info.holder(), map);
   7606 
   7607     HValue* function = Add<HConstant>(expr->target());
   7608     environment()->SetExpressionStackAt(0, function);
   7609     Push(receiver);
   7610     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   7611     bool needs_wrapping = NeedsWrappingFor(info.type(), target);
   7612     bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
   7613     if (FLAG_trace_inlining && try_inline) {
   7614       Handle<JSFunction> caller = current_info()->closure();
   7615       SmartArrayPointer<char> caller_name =
   7616           caller->shared()->DebugName()->ToCString();
   7617       PrintF("Trying to inline the polymorphic call to %s from %s\n",
   7618              name->ToCString().get(),
   7619              caller_name.get());
   7620     }
   7621     if (try_inline && TryInlineCall(expr)) {
   7622       // Trying to inline will signal that we should bailout from the
   7623       // entire compilation by setting stack overflow on the visitor.
   7624       if (HasStackOverflow()) return;
   7625     } else {
   7626       // Since HWrapReceiver currently cannot actually wrap numbers and strings,
   7627       // use the regular CallFunctionStub for method calls to wrap the receiver.
   7628       // TODO(verwaest): Support creation of value wrappers directly in
   7629       // HWrapReceiver.
   7630       HInstruction* call = needs_wrapping
   7631           ? NewUncasted<HCallFunction>(
   7632               function, argument_count, WRAP_AND_CALL)
   7633           : BuildCallConstantFunction(target, argument_count);
   7634       PushArgumentsFromEnvironment(argument_count);
   7635       AddInstruction(call);
   7636       Drop(1);  // Drop the function.
   7637       if (!ast_context()->IsEffect()) Push(call);
   7638     }
   7639 
   7640     if (current_block() != NULL) Goto(join);
   7641     set_current_block(if_false);
   7642   }
   7643 
   7644   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
   7645   // know about and do not want to handle ones we've never seen.  Otherwise
   7646   // use a generic IC.
   7647   if (ordered_functions == types->length() && FLAG_deoptimize_uncommon_cases) {
   7648     FinishExitWithHardDeoptimization("Unknown map in polymorphic call");
   7649   } else {
   7650     Property* prop = expr->expression()->AsProperty();
   7651     HInstruction* function = BuildNamedGeneric(
   7652         LOAD, prop, receiver, name, NULL, prop->IsUninitialized());
   7653     AddInstruction(function);
   7654     Push(function);
   7655     AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
   7656 
   7657     environment()->SetExpressionStackAt(1, function);
   7658     environment()->SetExpressionStackAt(0, receiver);
   7659     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   7660 
   7661     CallFunctionFlags flags = receiver->type().IsJSObject()
   7662         ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
   7663     HInstruction* call = New<HCallFunction>(
   7664         function, argument_count, flags);
   7665 
   7666     PushArgumentsFromEnvironment(argument_count);
   7667 
   7668     Drop(1);  // Function.
   7669 
   7670     if (join != NULL) {
   7671       AddInstruction(call);
   7672       if (!ast_context()->IsEffect()) Push(call);
   7673       Goto(join);
   7674     } else {
   7675       return ast_context()->ReturnInstruction(call, expr->id());
   7676     }
   7677   }
   7678 
   7679   // We assume that control flow is always live after an expression.  So
   7680   // even without predecessors to the join block, we set it as the exit
   7681   // block and continue by adding instructions there.
   7682   DCHECK(join != NULL);
   7683   if (join->HasPredecessor()) {
   7684     set_current_block(join);
   7685     join->SetJoinId(expr->id());
   7686     if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
   7687   } else {
   7688     set_current_block(NULL);
   7689   }
   7690 }
   7691 
   7692 
   7693 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
   7694                                          Handle<JSFunction> caller,
   7695                                          const char* reason) {
   7696   if (FLAG_trace_inlining) {
   7697     SmartArrayPointer<char> target_name =
   7698         target->shared()->DebugName()->ToCString();
   7699     SmartArrayPointer<char> caller_name =
   7700         caller->shared()->DebugName()->ToCString();
   7701     if (reason == NULL) {
   7702       PrintF("Inlined %s called from %s.\n", target_name.get(),
   7703              caller_name.get());
   7704     } else {
   7705       PrintF("Did not inline %s called from %s (%s).\n",
   7706              target_name.get(), caller_name.get(), reason);
   7707     }
   7708   }
   7709 }
   7710 
   7711 
   7712 static const int kNotInlinable = 1000000000;
   7713 
   7714 
   7715 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
   7716   if (!FLAG_use_inlining) return kNotInlinable;
   7717 
   7718   // Precondition: call is monomorphic and we have found a target with the
   7719   // appropriate arity.
   7720   Handle<JSFunction> caller = current_info()->closure();
   7721   Handle<SharedFunctionInfo> target_shared(target->shared());
   7722 
   7723   // Always inline builtins marked for inlining.
   7724   if (target->IsBuiltin()) {
   7725     return target_shared->inline_builtin() ? 0 : kNotInlinable;
   7726   }
   7727 
   7728   if (target_shared->IsApiFunction()) {
   7729     TraceInline(target, caller, "target is api function");
   7730     return kNotInlinable;
   7731   }
   7732 
   7733   // Do a quick check on source code length to avoid parsing large
   7734   // inlining candidates.
   7735   if (target_shared->SourceSize() >
   7736       Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
   7737     TraceInline(target, caller, "target text too big");
   7738     return kNotInlinable;
   7739   }
   7740 
   7741   // Target must be inlineable.
   7742   if (!target_shared->IsInlineable()) {
   7743     TraceInline(target, caller, "target not inlineable");
   7744     return kNotInlinable;
   7745   }
   7746   if (target_shared->DisableOptimizationReason() != kNoReason) {
   7747     TraceInline(target, caller, "target contains unsupported syntax [early]");
   7748     return kNotInlinable;
   7749   }
   7750 
   7751   int nodes_added = target_shared->ast_node_count();
   7752   return nodes_added;
   7753 }
   7754 
   7755 
   7756 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
   7757                                        int arguments_count,
   7758                                        HValue* implicit_return_value,
   7759                                        BailoutId ast_id,
   7760                                        BailoutId return_id,
   7761                                        InliningKind inlining_kind,
   7762                                        HSourcePosition position) {
   7763   int nodes_added = InliningAstSize(target);
   7764   if (nodes_added == kNotInlinable) return false;
   7765 
   7766   Handle<JSFunction> caller = current_info()->closure();
   7767 
   7768   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
   7769     TraceInline(target, caller, "target AST is too large [early]");
   7770     return false;
   7771   }
   7772 
   7773   // Don't inline deeper than the maximum number of inlining levels.
   7774   HEnvironment* env = environment();
   7775   int current_level = 1;
   7776   while (env->outer() != NULL) {
   7777     if (current_level == FLAG_max_inlining_levels) {
   7778       TraceInline(target, caller, "inline depth limit reached");
   7779       return false;
   7780     }
   7781     if (env->outer()->frame_type() == JS_FUNCTION) {
   7782       current_level++;
   7783     }
   7784     env = env->outer();
   7785   }
   7786 
   7787   // Don't inline recursive functions.
   7788   for (FunctionState* state = function_state();
   7789        state != NULL;
   7790        state = state->outer()) {
   7791     if (*state->compilation_info()->closure() == *target) {
   7792       TraceInline(target, caller, "target is recursive");
   7793       return false;
   7794     }
   7795   }
   7796 
   7797   // We don't want to add more than a certain number of nodes from inlining.
   7798   if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
   7799                            kUnlimitedMaxInlinedNodesCumulative)) {
   7800     TraceInline(target, caller, "cumulative AST node limit reached");
   7801     return false;
   7802   }
   7803 
   7804   // Parse and allocate variables.
   7805   CompilationInfo target_info(target, zone());
   7806   // Use the same AstValueFactory for creating strings in the sub-compilation
   7807   // step, but don't transfer ownership to target_info.
   7808   target_info.SetAstValueFactory(top_info()->ast_value_factory(), false);
   7809   Handle<SharedFunctionInfo> target_shared(target->shared());
   7810   if (!Parser::Parse(&target_info) || !Scope::Analyze(&target_info)) {
   7811     if (target_info.isolate()->has_pending_exception()) {
   7812       // Parse or scope error, never optimize this function.
   7813       SetStackOverflow();
   7814       target_shared->DisableOptimization(kParseScopeError);
   7815     }
   7816     TraceInline(target, caller, "parse failure");
   7817     return false;
   7818   }
   7819 
   7820   if (target_info.scope()->num_heap_slots() > 0) {
   7821     TraceInline(target, caller, "target has context-allocated variables");
   7822     return false;
   7823   }
   7824   FunctionLiteral* function = target_info.function();
   7825 
   7826   // The following conditions must be checked again after re-parsing, because
   7827   // earlier the information might not have been complete due to lazy parsing.
   7828   nodes_added = function->ast_node_count();
   7829   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
   7830     TraceInline(target, caller, "target AST is too large [late]");
   7831     return false;
   7832   }
   7833   if (function->dont_optimize()) {
   7834     TraceInline(target, caller, "target contains unsupported syntax [late]");
   7835     return false;
   7836   }
   7837 
   7838   // If the function uses the arguments object check that inlining of functions
   7839   // with arguments object is enabled and the arguments-variable is
   7840   // stack allocated.
   7841   if (function->scope()->arguments() != NULL) {
   7842     if (!FLAG_inline_arguments) {
   7843       TraceInline(target, caller, "target uses arguments object");
   7844       return false;
   7845     }
   7846 
   7847     if (!function->scope()->arguments()->IsStackAllocated()) {
   7848       TraceInline(target,
   7849                   caller,
   7850                   "target uses non-stackallocated arguments object");
   7851       return false;
   7852     }
   7853   }
   7854 
   7855   // All declarations must be inlineable.
   7856   ZoneList<Declaration*>* decls = target_info.scope()->declarations();
   7857   int decl_count = decls->length();
   7858   for (int i = 0; i < decl_count; ++i) {
   7859     if (!decls->at(i)->IsInlineable()) {
   7860       TraceInline(target, caller, "target has non-trivial declaration");
   7861       return false;
   7862     }
   7863   }
   7864 
   7865   // Generate the deoptimization data for the unoptimized version of
   7866   // the target function if we don't already have it.
   7867   if (!Compiler::EnsureDeoptimizationSupport(&target_info)) {
   7868     TraceInline(target, caller, "could not generate deoptimization info");
   7869     return false;
   7870   }
   7871 
   7872   // ----------------------------------------------------------------
   7873   // After this point, we've made a decision to inline this function (so
   7874   // TryInline should always return true).
   7875 
   7876   // Type-check the inlined function.
   7877   DCHECK(target_shared->has_deoptimization_support());
   7878   AstTyper::Run(&target_info);
   7879 
   7880   int function_id = graph()->TraceInlinedFunction(target_shared, position);
   7881 
   7882   // Save the pending call context. Set up new one for the inlined function.
   7883   // The function state is new-allocated because we need to delete it
   7884   // in two different places.
   7885   FunctionState* target_state = new FunctionState(
   7886       this, &target_info, inlining_kind, function_id);
   7887 
   7888   HConstant* undefined = graph()->GetConstantUndefined();
   7889 
   7890   HEnvironment* inner_env =
   7891       environment()->CopyForInlining(target,
   7892                                      arguments_count,
   7893                                      function,
   7894                                      undefined,
   7895                                      function_state()->inlining_kind());
   7896 
   7897   HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
   7898   inner_env->BindContext(context);
   7899 
   7900   // Create a dematerialized arguments object for the function, also copy the
   7901   // current arguments values to use them for materialization.
   7902   HEnvironment* arguments_env = inner_env->arguments_environment();
   7903   int parameter_count = arguments_env->parameter_count();
   7904   HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
   7905   for (int i = 0; i < parameter_count; i++) {
   7906     arguments_object->AddArgument(arguments_env->Lookup(i), zone());
   7907   }
   7908 
   7909   // If the function uses arguments object then bind bind one.
   7910   if (function->scope()->arguments() != NULL) {
   7911     DCHECK(function->scope()->arguments()->IsStackAllocated());
   7912     inner_env->Bind(function->scope()->arguments(), arguments_object);
   7913   }
   7914 
   7915   // Capture the state before invoking the inlined function for deopt in the
   7916   // inlined function. This simulate has no bailout-id since it's not directly
   7917   // reachable for deopt, and is only used to capture the state. If the simulate
   7918   // becomes reachable by merging, the ast id of the simulate merged into it is
   7919   // adopted.
   7920   Add<HSimulate>(BailoutId::None());
   7921 
   7922   current_block()->UpdateEnvironment(inner_env);
   7923   Scope* saved_scope = scope();
   7924   set_scope(target_info.scope());
   7925   HEnterInlined* enter_inlined =
   7926       Add<HEnterInlined>(return_id, target, context, arguments_count, function,
   7927                          function_state()->inlining_kind(),
   7928                          function->scope()->arguments(), arguments_object);
   7929   function_state()->set_entry(enter_inlined);
   7930 
   7931   VisitDeclarations(target_info.scope()->declarations());
   7932   VisitStatements(function->body());
   7933   set_scope(saved_scope);
   7934   if (HasStackOverflow()) {
   7935     // Bail out if the inline function did, as we cannot residualize a call
   7936     // instead, but do not disable optimization for the outer function.
   7937     TraceInline(target, caller, "inline graph construction failed");
   7938     target_shared->DisableOptimization(kInliningBailedOut);
   7939     current_info()->RetryOptimization(kInliningBailedOut);
   7940     delete target_state;
   7941     return true;
   7942   }
   7943 
   7944   // Update inlined nodes count.
   7945   inlined_count_ += nodes_added;
   7946 
   7947   Handle<Code> unoptimized_code(target_shared->code());
   7948   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
   7949   Handle<TypeFeedbackInfo> type_info(
   7950       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
   7951   graph()->update_type_change_checksum(type_info->own_type_change_checksum());
   7952 
   7953   TraceInline(target, caller, NULL);
   7954 
   7955   if (current_block() != NULL) {
   7956     FunctionState* state = function_state();
   7957     if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
   7958       // Falling off the end of an inlined construct call. In a test context the
   7959       // return value will always evaluate to true, in a value context the
   7960       // return value is the newly allocated receiver.
   7961       if (call_context()->IsTest()) {
   7962         Goto(inlined_test_context()->if_true(), state);
   7963       } else if (call_context()->IsEffect()) {
   7964         Goto(function_return(), state);
   7965       } else {
   7966         DCHECK(call_context()->IsValue());
   7967         AddLeaveInlined(implicit_return_value, state);
   7968       }
   7969     } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
   7970       // Falling off the end of an inlined setter call. The returned value is
   7971       // never used, the value of an assignment is always the value of the RHS
   7972       // of the assignment.
   7973       if (call_context()->IsTest()) {
   7974         inlined_test_context()->ReturnValue(implicit_return_value);
   7975       } else if (call_context()->IsEffect()) {
   7976         Goto(function_return(), state);
   7977       } else {
   7978         DCHECK(call_context()->IsValue());
   7979         AddLeaveInlined(implicit_return_value, state);
   7980       }
   7981     } else {
   7982       // Falling off the end of a normal inlined function. This basically means
   7983       // returning undefined.
   7984       if (call_context()->IsTest()) {
   7985         Goto(inlined_test_context()->if_false(), state);
   7986       } else if (call_context()->IsEffect()) {
   7987         Goto(function_return(), state);
   7988       } else {
   7989         DCHECK(call_context()->IsValue());
   7990         AddLeaveInlined(undefined, state);
   7991       }
   7992     }
   7993   }
   7994 
   7995   // Fix up the function exits.
   7996   if (inlined_test_context() != NULL) {
   7997     HBasicBlock* if_true = inlined_test_context()->if_true();
   7998     HBasicBlock* if_false = inlined_test_context()->if_false();
   7999 
   8000     HEnterInlined* entry = function_state()->entry();
   8001 
   8002     // Pop the return test context from the expression context stack.
   8003     DCHECK(ast_context() == inlined_test_context());
   8004     ClearInlinedTestContext();
   8005     delete target_state;
   8006 
   8007     // Forward to the real test context.
   8008     if (if_true->HasPredecessor()) {
   8009       entry->RegisterReturnTarget(if_true, zone());
   8010       if_true->SetJoinId(ast_id);
   8011       HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
   8012       Goto(if_true, true_target, function_state());
   8013     }
   8014     if (if_false->HasPredecessor()) {
   8015       entry->RegisterReturnTarget(if_false, zone());
   8016       if_false->SetJoinId(ast_id);
   8017       HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
   8018       Goto(if_false, false_target, function_state());
   8019     }
   8020     set_current_block(NULL);
   8021     return true;
   8022 
   8023   } else if (function_return()->HasPredecessor()) {
   8024     function_state()->entry()->RegisterReturnTarget(function_return(), zone());
   8025     function_return()->SetJoinId(ast_id);
   8026     set_current_block(function_return());
   8027   } else {
   8028     set_current_block(NULL);
   8029   }
   8030   delete target_state;
   8031   return true;
   8032 }
   8033 
   8034 
   8035 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
   8036   return TryInline(expr->target(),
   8037                    expr->arguments()->length(),
   8038                    NULL,
   8039                    expr->id(),
   8040                    expr->ReturnId(),
   8041                    NORMAL_RETURN,
   8042                    ScriptPositionToSourcePosition(expr->position()));
   8043 }
   8044 
   8045 
   8046 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
   8047                                                 HValue* implicit_return_value) {
   8048   return TryInline(expr->target(),
   8049                    expr->arguments()->length(),
   8050                    implicit_return_value,
   8051                    expr->id(),
   8052                    expr->ReturnId(),
   8053                    CONSTRUCT_CALL_RETURN,
   8054                    ScriptPositionToSourcePosition(expr->position()));
   8055 }
   8056 
   8057 
   8058 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
   8059                                              Handle<Map> receiver_map,
   8060                                              BailoutId ast_id,
   8061                                              BailoutId return_id) {
   8062   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
   8063   return TryInline(getter,
   8064                    0,
   8065                    NULL,
   8066                    ast_id,
   8067                    return_id,
   8068                    GETTER_CALL_RETURN,
   8069                    source_position());
   8070 }
   8071 
   8072 
   8073 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
   8074                                              Handle<Map> receiver_map,
   8075                                              BailoutId id,
   8076                                              BailoutId assignment_id,
   8077                                              HValue* implicit_return_value) {
   8078   if (TryInlineApiSetter(setter, receiver_map, id)) return true;
   8079   return TryInline(setter,
   8080                    1,
   8081                    implicit_return_value,
   8082                    id, assignment_id,
   8083                    SETTER_CALL_RETURN,
   8084                    source_position());
   8085 }
   8086 
   8087 
   8088 bool HOptimizedGraphBuilder::TryInlineApply(Handle<JSFunction> function,
   8089                                             Call* expr,
   8090                                             int arguments_count) {
   8091   return TryInline(function,
   8092                    arguments_count,
   8093                    NULL,
   8094                    expr->id(),
   8095                    expr->ReturnId(),
   8096                    NORMAL_RETURN,
   8097                    ScriptPositionToSourcePosition(expr->position()));
   8098 }
   8099 
   8100 
   8101 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
   8102   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
   8103   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
   8104   switch (id) {
   8105     case kMathExp:
   8106       if (!FLAG_fast_math) break;
   8107       // Fall through if FLAG_fast_math.
   8108     case kMathRound:
   8109     case kMathFround:
   8110     case kMathFloor:
   8111     case kMathAbs:
   8112     case kMathSqrt:
   8113     case kMathLog:
   8114     case kMathClz32:
   8115       if (expr->arguments()->length() == 1) {
   8116         HValue* argument = Pop();
   8117         Drop(2);  // Receiver and function.
   8118         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
   8119         ast_context()->ReturnInstruction(op, expr->id());
   8120         return true;
   8121       }
   8122       break;
   8123     case kMathImul:
   8124       if (expr->arguments()->length() == 2) {
   8125         HValue* right = Pop();
   8126         HValue* left = Pop();
   8127         Drop(2);  // Receiver and function.
   8128         HInstruction* op = HMul::NewImul(zone(), context(), left, right);
   8129         ast_context()->ReturnInstruction(op, expr->id());
   8130         return true;
   8131       }
   8132       break;
   8133     default:
   8134       // Not supported for inlining yet.
   8135       break;
   8136   }
   8137   return false;
   8138 }
   8139 
   8140 
   8141 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
   8142     Call* expr,
   8143     HValue* receiver,
   8144     Handle<Map> receiver_map) {
   8145   // Try to inline calls like Math.* as operations in the calling function.
   8146   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
   8147   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
   8148   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
   8149   switch (id) {
   8150     case kStringCharCodeAt:
   8151     case kStringCharAt:
   8152       if (argument_count == 2) {
   8153         HValue* index = Pop();
   8154         HValue* string = Pop();
   8155         Drop(1);  // Function.
   8156         HInstruction* char_code =
   8157             BuildStringCharCodeAt(string, index);
   8158         if (id == kStringCharCodeAt) {
   8159           ast_context()->ReturnInstruction(char_code, expr->id());
   8160           return true;
   8161         }
   8162         AddInstruction(char_code);
   8163         HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
   8164         ast_context()->ReturnInstruction(result, expr->id());
   8165         return true;
   8166       }
   8167       break;
   8168     case kStringFromCharCode:
   8169       if (argument_count == 2) {
   8170         HValue* argument = Pop();
   8171         Drop(2);  // Receiver and function.
   8172         HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
   8173         ast_context()->ReturnInstruction(result, expr->id());
   8174         return true;
   8175       }
   8176       break;
   8177     case kMathExp:
   8178       if (!FLAG_fast_math) break;
   8179       // Fall through if FLAG_fast_math.
   8180     case kMathRound:
   8181     case kMathFround:
   8182     case kMathFloor:
   8183     case kMathAbs:
   8184     case kMathSqrt:
   8185     case kMathLog:
   8186     case kMathClz32:
   8187       if (argument_count == 2) {
   8188         HValue* argument = Pop();
   8189         Drop(2);  // Receiver and function.
   8190         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
   8191         ast_context()->ReturnInstruction(op, expr->id());
   8192         return true;
   8193       }
   8194       break;
   8195     case kMathPow:
   8196       if (argument_count == 3) {
   8197         HValue* right = Pop();
   8198         HValue* left = Pop();
   8199         Drop(2);  // Receiver and function.
   8200         HInstruction* result = NULL;
   8201         // Use sqrt() if exponent is 0.5 or -0.5.
   8202         if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
   8203           double exponent = HConstant::cast(right)->DoubleValue();
   8204           if (exponent == 0.5) {
   8205             result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
   8206           } else if (exponent == -0.5) {
   8207             HValue* one = graph()->GetConstant1();
   8208             HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
   8209                 left, kMathPowHalf);
   8210             // MathPowHalf doesn't have side effects so there's no need for
   8211             // an environment simulation here.
   8212             DCHECK(!sqrt->HasObservableSideEffects());
   8213             result = NewUncasted<HDiv>(one, sqrt);
   8214           } else if (exponent == 2.0) {
   8215             result = NewUncasted<HMul>(left, left);
   8216           }
   8217         }
   8218 
   8219         if (result == NULL) {
   8220           result = NewUncasted<HPower>(left, right);
   8221         }
   8222         ast_context()->ReturnInstruction(result, expr->id());
   8223         return true;
   8224       }
   8225       break;
   8226     case kMathMax:
   8227     case kMathMin:
   8228       if (argument_count == 3) {
   8229         HValue* right = Pop();
   8230         HValue* left = Pop();
   8231         Drop(2);  // Receiver and function.
   8232         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
   8233                                                      : HMathMinMax::kMathMax;
   8234         HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
   8235         ast_context()->ReturnInstruction(result, expr->id());
   8236         return true;
   8237       }
   8238       break;
   8239     case kMathImul:
   8240       if (argument_count == 3) {
   8241         HValue* right = Pop();
   8242         HValue* left = Pop();
   8243         Drop(2);  // Receiver and function.
   8244         HInstruction* result = HMul::NewImul(zone(), context(), left, right);
   8245         ast_context()->ReturnInstruction(result, expr->id());
   8246         return true;
   8247       }
   8248       break;
   8249     case kArrayPop: {
   8250       if (receiver_map.is_null()) return false;
   8251       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
   8252       ElementsKind elements_kind = receiver_map->elements_kind();
   8253       if (!IsFastElementsKind(elements_kind)) return false;
   8254       if (receiver_map->is_observed()) return false;
   8255       if (!receiver_map->is_extensible()) return false;
   8256 
   8257       Drop(expr->arguments()->length());
   8258       HValue* result;
   8259       HValue* reduced_length;
   8260       HValue* receiver = Pop();
   8261 
   8262       HValue* checked_object = AddCheckMap(receiver, receiver_map);
   8263       HValue* length = Add<HLoadNamedField>(
   8264           checked_object, static_cast<HValue*>(NULL),
   8265           HObjectAccess::ForArrayLength(elements_kind));
   8266 
   8267       Drop(1);  // Function.
   8268 
   8269       { NoObservableSideEffectsScope scope(this);
   8270         IfBuilder length_checker(this);
   8271 
   8272         HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
   8273             length, graph()->GetConstant0(), Token::EQ);
   8274         length_checker.Then();
   8275 
   8276         if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
   8277 
   8278         length_checker.Else();
   8279         HValue* elements = AddLoadElements(checked_object);
   8280         // Ensure that we aren't popping from a copy-on-write array.
   8281         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   8282           elements = BuildCopyElementsOnWrite(checked_object, elements,
   8283                                               elements_kind, length);
   8284         }
   8285         reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
   8286         result = AddElementAccess(elements, reduced_length, NULL,
   8287                                   bounds_check, elements_kind, LOAD);
   8288         Factory* factory = isolate()->factory();
   8289         double nan_double = FixedDoubleArray::hole_nan_as_double();
   8290         HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
   8291             ? Add<HConstant>(factory->the_hole_value())
   8292             : Add<HConstant>(nan_double);
   8293         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   8294           elements_kind = FAST_HOLEY_ELEMENTS;
   8295         }
   8296         AddElementAccess(
   8297             elements, reduced_length, hole, bounds_check, elements_kind, STORE);
   8298         Add<HStoreNamedField>(
   8299             checked_object, HObjectAccess::ForArrayLength(elements_kind),
   8300             reduced_length, STORE_TO_INITIALIZED_ENTRY);
   8301 
   8302         if (!ast_context()->IsEffect()) Push(result);
   8303 
   8304         length_checker.End();
   8305       }
   8306       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
   8307       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   8308       if (!ast_context()->IsEffect()) Drop(1);
   8309 
   8310       ast_context()->ReturnValue(result);
   8311       return true;
   8312     }
   8313     case kArrayPush: {
   8314       if (receiver_map.is_null()) return false;
   8315       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
   8316       ElementsKind elements_kind = receiver_map->elements_kind();
   8317       if (!IsFastElementsKind(elements_kind)) return false;
   8318       if (receiver_map->is_observed()) return false;
   8319       if (JSArray::IsReadOnlyLengthDescriptor(receiver_map)) return false;
   8320       if (!receiver_map->is_extensible()) return false;
   8321 
   8322       // If there may be elements accessors in the prototype chain, the fast
   8323       // inlined version can't be used.
   8324       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8325       // If there currently can be no elements accessors on the prototype chain,
   8326       // it doesn't mean that there won't be any later. Install a full prototype
   8327       // chain check to trap element accessors being installed on the prototype
   8328       // chain, which would cause elements to go to dictionary mode and result
   8329       // in a map change.
   8330       Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
   8331       BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
   8332 
   8333       const int argc = expr->arguments()->length();
   8334       if (argc != 1) return false;
   8335 
   8336       HValue* value_to_push = Pop();
   8337       HValue* array = Pop();
   8338       Drop(1);  // Drop function.
   8339 
   8340       HInstruction* new_size = NULL;
   8341       HValue* length = NULL;
   8342 
   8343       {
   8344         NoObservableSideEffectsScope scope(this);
   8345 
   8346         length = Add<HLoadNamedField>(array, static_cast<HValue*>(NULL),
   8347           HObjectAccess::ForArrayLength(elements_kind));
   8348 
   8349         new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
   8350 
   8351         bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
   8352         BuildUncheckedMonomorphicElementAccess(array, length,
   8353                                                value_to_push, is_array,
   8354                                                elements_kind, STORE,
   8355                                                NEVER_RETURN_HOLE,
   8356                                                STORE_AND_GROW_NO_TRANSITION);
   8357 
   8358         if (!ast_context()->IsEffect()) Push(new_size);
   8359         Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   8360         if (!ast_context()->IsEffect()) Drop(1);
   8361       }
   8362 
   8363       ast_context()->ReturnValue(new_size);
   8364       return true;
   8365     }
   8366     case kArrayShift: {
   8367       if (receiver_map.is_null()) return false;
   8368       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
   8369       ElementsKind kind = receiver_map->elements_kind();
   8370       if (!IsFastElementsKind(kind)) return false;
   8371       if (receiver_map->is_observed()) return false;
   8372       if (!receiver_map->is_extensible()) return false;
   8373 
   8374       // If there may be elements accessors in the prototype chain, the fast
   8375       // inlined version can't be used.
   8376       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8377 
   8378       // If there currently can be no elements accessors on the prototype chain,
   8379       // it doesn't mean that there won't be any later. Install a full prototype
   8380       // chain check to trap element accessors being installed on the prototype
   8381       // chain, which would cause elements to go to dictionary mode and result
   8382       // in a map change.
   8383       BuildCheckPrototypeMaps(
   8384           handle(JSObject::cast(receiver_map->prototype()), isolate()),
   8385           Handle<JSObject>::null());
   8386 
   8387       // Threshold for fast inlined Array.shift().
   8388       HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
   8389 
   8390       Drop(expr->arguments()->length());
   8391       HValue* receiver = Pop();
   8392       HValue* function = Pop();
   8393       HValue* result;
   8394 
   8395       {
   8396         NoObservableSideEffectsScope scope(this);
   8397 
   8398         HValue* length = Add<HLoadNamedField>(
   8399             receiver, static_cast<HValue*>(NULL),
   8400             HObjectAccess::ForArrayLength(kind));
   8401 
   8402         IfBuilder if_lengthiszero(this);
   8403         HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
   8404             length, graph()->GetConstant0(), Token::EQ);
   8405         if_lengthiszero.Then();
   8406         {
   8407           if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
   8408         }
   8409         if_lengthiszero.Else();
   8410         {
   8411           HValue* elements = AddLoadElements(receiver);
   8412 
   8413           // Check if we can use the fast inlined Array.shift().
   8414           IfBuilder if_inline(this);
   8415           if_inline.If<HCompareNumericAndBranch>(
   8416               length, inline_threshold, Token::LTE);
   8417           if (IsFastSmiOrObjectElementsKind(kind)) {
   8418             // We cannot handle copy-on-write backing stores here.
   8419             if_inline.AndIf<HCompareMap>(
   8420                 elements, isolate()->factory()->fixed_array_map());
   8421           }
   8422           if_inline.Then();
   8423           {
   8424             // Remember the result.
   8425             if (!ast_context()->IsEffect()) {
   8426               Push(AddElementAccess(elements, graph()->GetConstant0(), NULL,
   8427                                     lengthiszero, kind, LOAD));
   8428             }
   8429 
   8430             // Compute the new length.
   8431             HValue* new_length = AddUncasted<HSub>(
   8432                 length, graph()->GetConstant1());
   8433             new_length->ClearFlag(HValue::kCanOverflow);
   8434 
   8435             // Copy the remaining elements.
   8436             LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
   8437             {
   8438               HValue* new_key = loop.BeginBody(
   8439                   graph()->GetConstant0(), new_length, Token::LT);
   8440               HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
   8441               key->ClearFlag(HValue::kCanOverflow);
   8442               HValue* element = AddUncasted<HLoadKeyed>(
   8443                   elements, key, lengthiszero, kind, ALLOW_RETURN_HOLE);
   8444               HStoreKeyed* store = Add<HStoreKeyed>(
   8445                   elements, new_key, element, kind);
   8446               store->SetFlag(HValue::kAllowUndefinedAsNaN);
   8447             }
   8448             loop.EndBody();
   8449 
   8450             // Put a hole at the end.
   8451             HValue* hole = IsFastSmiOrObjectElementsKind(kind)
   8452                 ? Add<HConstant>(isolate()->factory()->the_hole_value())
   8453                 : Add<HConstant>(FixedDoubleArray::hole_nan_as_double());
   8454             if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
   8455             Add<HStoreKeyed>(
   8456                 elements, new_length, hole, kind, INITIALIZING_STORE);
   8457 
   8458             // Remember new length.
   8459             Add<HStoreNamedField>(
   8460                 receiver, HObjectAccess::ForArrayLength(kind),
   8461                 new_length, STORE_TO_INITIALIZED_ENTRY);
   8462           }
   8463           if_inline.Else();
   8464           {
   8465             Add<HPushArguments>(receiver);
   8466             result = Add<HCallJSFunction>(function, 1, true);
   8467             if (!ast_context()->IsEffect()) Push(result);
   8468           }
   8469           if_inline.End();
   8470         }
   8471         if_lengthiszero.End();
   8472       }
   8473       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
   8474       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   8475       if (!ast_context()->IsEffect()) Drop(1);
   8476       ast_context()->ReturnValue(result);
   8477       return true;
   8478     }
   8479     case kArrayIndexOf:
   8480     case kArrayLastIndexOf: {
   8481       if (receiver_map.is_null()) return false;
   8482       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
   8483       ElementsKind kind = receiver_map->elements_kind();
   8484       if (!IsFastElementsKind(kind)) return false;
   8485       if (receiver_map->is_observed()) return false;
   8486       if (argument_count != 2) return false;
   8487       if (!receiver_map->is_extensible()) return false;
   8488 
   8489       // If there may be elements accessors in the prototype chain, the fast
   8490       // inlined version can't be used.
   8491       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8492 
   8493       // If there currently can be no elements accessors on the prototype chain,
   8494       // it doesn't mean that there won't be any later. Install a full prototype
   8495       // chain check to trap element accessors being installed on the prototype
   8496       // chain, which would cause elements to go to dictionary mode and result
   8497       // in a map change.
   8498       BuildCheckPrototypeMaps(
   8499           handle(JSObject::cast(receiver_map->prototype()), isolate()),
   8500           Handle<JSObject>::null());
   8501 
   8502       HValue* search_element = Pop();
   8503       HValue* receiver = Pop();
   8504       Drop(1);  // Drop function.
   8505 
   8506       ArrayIndexOfMode mode = (id == kArrayIndexOf)
   8507           ? kFirstIndexOf : kLastIndexOf;
   8508       HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
   8509 
   8510       if (!ast_context()->IsEffect()) Push(index);
   8511       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   8512       if (!ast_context()->IsEffect()) Drop(1);
   8513       ast_context()->ReturnValue(index);
   8514       return true;
   8515     }
   8516     default:
   8517       // Not yet supported for inlining.
   8518       break;
   8519   }
   8520   return false;
   8521 }
   8522 
   8523 
   8524 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
   8525                                                       HValue* receiver) {
   8526   Handle<JSFunction> function = expr->target();
   8527   int argc = expr->arguments()->length();
   8528   SmallMapList receiver_maps;
   8529   return TryInlineApiCall(function,
   8530                           receiver,
   8531                           &receiver_maps,
   8532                           argc,
   8533                           expr->id(),
   8534                           kCallApiFunction);
   8535 }
   8536 
   8537 
   8538 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
   8539     Call* expr,
   8540     HValue* receiver,
   8541     SmallMapList* receiver_maps) {
   8542   Handle<JSFunction> function = expr->target();
   8543   int argc = expr->arguments()->length();
   8544   return TryInlineApiCall(function,
   8545                           receiver,
   8546                           receiver_maps,
   8547                           argc,
   8548                           expr->id(),
   8549                           kCallApiMethod);
   8550 }
   8551 
   8552 
   8553 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
   8554                                                 Handle<Map> receiver_map,
   8555                                                 BailoutId ast_id) {
   8556   SmallMapList receiver_maps(1, zone());
   8557   receiver_maps.Add(receiver_map, zone());
   8558   return TryInlineApiCall(function,
   8559                           NULL,  // Receiver is on expression stack.
   8560                           &receiver_maps,
   8561                           0,
   8562                           ast_id,
   8563                           kCallApiGetter);
   8564 }
   8565 
   8566 
   8567 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function,
   8568                                                 Handle<Map> receiver_map,
   8569                                                 BailoutId ast_id) {
   8570   SmallMapList receiver_maps(1, zone());
   8571   receiver_maps.Add(receiver_map, zone());
   8572   return TryInlineApiCall(function,
   8573                           NULL,  // Receiver is on expression stack.
   8574                           &receiver_maps,
   8575                           1,
   8576                           ast_id,
   8577                           kCallApiSetter);
   8578 }
   8579 
   8580 
   8581 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
   8582                                                HValue* receiver,
   8583                                                SmallMapList* receiver_maps,
   8584                                                int argc,
   8585                                                BailoutId ast_id,
   8586                                                ApiCallType call_type) {
   8587   CallOptimization optimization(function);
   8588   if (!optimization.is_simple_api_call()) return false;
   8589   Handle<Map> holder_map;
   8590   if (call_type == kCallApiFunction) {
   8591     // Cannot embed a direct reference to the global proxy map
   8592     // as it maybe dropped on deserialization.
   8593     CHECK(!isolate()->serializer_enabled());
   8594     DCHECK_EQ(0, receiver_maps->length());
   8595     receiver_maps->Add(handle(function->global_proxy()->map()), zone());
   8596   }
   8597   CallOptimization::HolderLookup holder_lookup =
   8598       CallOptimization::kHolderNotFound;
   8599   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
   8600       receiver_maps->first(), &holder_lookup);
   8601   if (holder_lookup == CallOptimization::kHolderNotFound) return false;
   8602 
   8603   if (FLAG_trace_inlining) {
   8604     PrintF("Inlining api function ");
   8605     function->ShortPrint();
   8606     PrintF("\n");
   8607   }
   8608 
   8609   bool drop_extra = false;
   8610   bool is_store = false;
   8611   switch (call_type) {
   8612     case kCallApiFunction:
   8613     case kCallApiMethod:
   8614       // Need to check that none of the receiver maps could have changed.
   8615       Add<HCheckMaps>(receiver, receiver_maps);
   8616       // Need to ensure the chain between receiver and api_holder is intact.
   8617       if (holder_lookup == CallOptimization::kHolderFound) {
   8618         AddCheckPrototypeMaps(api_holder, receiver_maps->first());
   8619       } else {
   8620         DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
   8621       }
   8622       // Includes receiver.
   8623       PushArgumentsFromEnvironment(argc + 1);
   8624       // Drop function after call.
   8625       drop_extra = true;
   8626       break;
   8627     case kCallApiGetter:
   8628       // Receiver and prototype chain cannot have changed.
   8629       DCHECK_EQ(0, argc);
   8630       DCHECK_EQ(NULL, receiver);
   8631       // Receiver is on expression stack.
   8632       receiver = Pop();
   8633       Add<HPushArguments>(receiver);
   8634       break;
   8635     case kCallApiSetter:
   8636       {
   8637         is_store = true;
   8638         // Receiver and prototype chain cannot have changed.
   8639         DCHECK_EQ(1, argc);
   8640         DCHECK_EQ(NULL, receiver);
   8641         // Receiver and value are on expression stack.
   8642         HValue* value = Pop();
   8643         receiver = Pop();
   8644         Add<HPushArguments>(receiver, value);
   8645         break;
   8646      }
   8647   }
   8648 
   8649   HValue* holder = NULL;
   8650   switch (holder_lookup) {
   8651     case CallOptimization::kHolderFound:
   8652       holder = Add<HConstant>(api_holder);
   8653       break;
   8654     case CallOptimization::kHolderIsReceiver:
   8655       holder = receiver;
   8656       break;
   8657     case CallOptimization::kHolderNotFound:
   8658       UNREACHABLE();
   8659       break;
   8660   }
   8661   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   8662   Handle<Object> call_data_obj(api_call_info->data(), isolate());
   8663   bool call_data_is_undefined = call_data_obj->IsUndefined();
   8664   HValue* call_data = Add<HConstant>(call_data_obj);
   8665   ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
   8666   ExternalReference ref = ExternalReference(&fun,
   8667                                             ExternalReference::DIRECT_API_CALL,
   8668                                             isolate());
   8669   HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
   8670 
   8671   HValue* op_vals[] = {
   8672     context(),
   8673     Add<HConstant>(function),
   8674     call_data,
   8675     holder,
   8676     api_function_address
   8677   };
   8678 
   8679   ApiFunctionDescriptor descriptor(isolate());
   8680   CallApiFunctionStub stub(isolate(), is_store, call_data_is_undefined, argc);
   8681   Handle<Code> code = stub.GetCode();
   8682   HConstant* code_value = Add<HConstant>(code);
   8683 
   8684   DCHECK((sizeof(op_vals) / kPointerSize) == descriptor.GetEnvironmentLength());
   8685 
   8686   HInstruction* call = New<HCallWithDescriptor>(
   8687       code_value, argc + 1, descriptor,
   8688       Vector<HValue*>(op_vals, descriptor.GetEnvironmentLength()));
   8689 
   8690   if (drop_extra) Drop(1);  // Drop function.
   8691   ast_context()->ReturnInstruction(call, ast_id);
   8692   return true;
   8693 }
   8694 
   8695 
   8696 bool HOptimizedGraphBuilder::TryCallApply(Call* expr) {
   8697   DCHECK(expr->expression()->IsProperty());
   8698 
   8699   if (!expr->IsMonomorphic()) {
   8700     return false;
   8701   }
   8702   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   8703   if (function_map->instance_type() != JS_FUNCTION_TYPE ||
   8704       !expr->target()->shared()->HasBuiltinFunctionId() ||
   8705       expr->target()->shared()->builtin_function_id() != kFunctionApply) {
   8706     return false;
   8707   }
   8708 
   8709   if (current_info()->scope()->arguments() == NULL) return false;
   8710 
   8711   ZoneList<Expression*>* args = expr->arguments();
   8712   if (args->length() != 2) return false;
   8713 
   8714   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
   8715   if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
   8716   HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
   8717   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
   8718 
   8719   // Found pattern f.apply(receiver, arguments).
   8720   CHECK_ALIVE_OR_RETURN(VisitForValue(args->at(0)), true);
   8721   HValue* receiver = Pop();  // receiver
   8722   HValue* function = Pop();  // f
   8723   Drop(1);  // apply
   8724 
   8725   HValue* checked_function = AddCheckMap(function, function_map);
   8726 
   8727   if (function_state()->outer() == NULL) {
   8728     HInstruction* elements = Add<HArgumentsElements>(false);
   8729     HInstruction* length = Add<HArgumentsLength>(elements);
   8730     HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
   8731     HInstruction* result = New<HApplyArguments>(function,
   8732                                                 wrapped_receiver,
   8733                                                 length,
   8734                                                 elements);
   8735     ast_context()->ReturnInstruction(result, expr->id());
   8736     return true;
   8737   } else {
   8738     // We are inside inlined function and we know exactly what is inside
   8739     // arguments object. But we need to be able to materialize at deopt.
   8740     DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
   8741               function_state()->entry()->arguments_object()->arguments_count());
   8742     HArgumentsObject* args = function_state()->entry()->arguments_object();
   8743     const ZoneList<HValue*>* arguments_values = args->arguments_values();
   8744     int arguments_count = arguments_values->length();
   8745     Push(function);
   8746     Push(BuildWrapReceiver(receiver, checked_function));
   8747     for (int i = 1; i < arguments_count; i++) {
   8748       Push(arguments_values->at(i));
   8749     }
   8750 
   8751     Handle<JSFunction> known_function;
   8752     if (function->IsConstant() &&
   8753         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   8754       known_function = Handle<JSFunction>::cast(
   8755           HConstant::cast(function)->handle(isolate()));
   8756       int args_count = arguments_count - 1;  // Excluding receiver.
   8757       if (TryInlineApply(known_function, expr, args_count)) return true;
   8758     }
   8759 
   8760     PushArgumentsFromEnvironment(arguments_count);
   8761     HInvokeFunction* call = New<HInvokeFunction>(
   8762         function, known_function, arguments_count);
   8763     Drop(1);  // Function.
   8764     ast_context()->ReturnInstruction(call, expr->id());
   8765     return true;
   8766   }
   8767 }
   8768 
   8769 
   8770 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
   8771                                                     Handle<JSFunction> target) {
   8772   SharedFunctionInfo* shared = target->shared();
   8773   if (shared->strict_mode() == SLOPPY && !shared->native()) {
   8774     // Cannot embed a direct reference to the global proxy
   8775     // as is it dropped on deserialization.
   8776     CHECK(!isolate()->serializer_enabled());
   8777     Handle<JSObject> global_proxy(target->context()->global_proxy());
   8778     return Add<HConstant>(global_proxy);
   8779   }
   8780   return graph()->GetConstantUndefined();
   8781 }
   8782 
   8783 
   8784 void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
   8785                                             int arguments_count,
   8786                                             HValue* function,
   8787                                             Handle<AllocationSite> site) {
   8788   Add<HCheckValue>(function, array_function());
   8789 
   8790   if (IsCallArrayInlineable(arguments_count, site)) {
   8791     BuildInlinedCallArray(expression, arguments_count, site);
   8792     return;
   8793   }
   8794 
   8795   HInstruction* call = PreProcessCall(New<HCallNewArray>(
   8796       function, arguments_count + 1, site->GetElementsKind()));
   8797   if (expression->IsCall()) {
   8798     Drop(1);
   8799   }
   8800   ast_context()->ReturnInstruction(call, expression->id());
   8801 }
   8802 
   8803 
   8804 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
   8805                                                   HValue* search_element,
   8806                                                   ElementsKind kind,
   8807                                                   ArrayIndexOfMode mode) {
   8808   DCHECK(IsFastElementsKind(kind));
   8809 
   8810   NoObservableSideEffectsScope no_effects(this);
   8811 
   8812   HValue* elements = AddLoadElements(receiver);
   8813   HValue* length = AddLoadArrayLength(receiver, kind);
   8814 
   8815   HValue* initial;
   8816   HValue* terminating;
   8817   Token::Value token;
   8818   LoopBuilder::Direction direction;
   8819   if (mode == kFirstIndexOf) {
   8820     initial = graph()->GetConstant0();
   8821     terminating = length;
   8822     token = Token::LT;
   8823     direction = LoopBuilder::kPostIncrement;
   8824   } else {
   8825     DCHECK_EQ(kLastIndexOf, mode);
   8826     initial = length;
   8827     terminating = graph()->GetConstant0();
   8828     token = Token::GT;
   8829     direction = LoopBuilder::kPreDecrement;
   8830   }
   8831 
   8832   Push(graph()->GetConstantMinus1());
   8833   if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
   8834     // Make sure that we can actually compare numbers correctly below, see
   8835     // https://code.google.com/p/chromium/issues/detail?id=407946 for details.
   8836     search_element = AddUncasted<HForceRepresentation>(
   8837         search_element, IsFastSmiElementsKind(kind) ? Representation::Smi()
   8838                                                     : Representation::Double());
   8839 
   8840     LoopBuilder loop(this, context(), direction);
   8841     {
   8842       HValue* index = loop.BeginBody(initial, terminating, token);
   8843       HValue* element = AddUncasted<HLoadKeyed>(
   8844           elements, index, static_cast<HValue*>(NULL),
   8845           kind, ALLOW_RETURN_HOLE);
   8846       IfBuilder if_issame(this);
   8847       if_issame.If<HCompareNumericAndBranch>(element, search_element,
   8848                                              Token::EQ_STRICT);
   8849       if_issame.Then();
   8850       {
   8851         Drop(1);
   8852         Push(index);
   8853         loop.Break();
   8854       }
   8855       if_issame.End();
   8856     }
   8857     loop.EndBody();
   8858   } else {
   8859     IfBuilder if_isstring(this);
   8860     if_isstring.If<HIsStringAndBranch>(search_element);
   8861     if_isstring.Then();
   8862     {
   8863       LoopBuilder loop(this, context(), direction);
   8864       {
   8865         HValue* index = loop.BeginBody(initial, terminating, token);
   8866         HValue* element = AddUncasted<HLoadKeyed>(
   8867             elements, index, static_cast<HValue*>(NULL),
   8868             kind, ALLOW_RETURN_HOLE);
   8869         IfBuilder if_issame(this);
   8870         if_issame.If<HIsStringAndBranch>(element);
   8871         if_issame.AndIf<HStringCompareAndBranch>(
   8872             element, search_element, Token::EQ_STRICT);
   8873         if_issame.Then();
   8874         {
   8875           Drop(1);
   8876           Push(index);
   8877           loop.Break();
   8878         }
   8879         if_issame.End();
   8880       }
   8881       loop.EndBody();
   8882     }
   8883     if_isstring.Else();
   8884     {
   8885       IfBuilder if_isnumber(this);
   8886       if_isnumber.If<HIsSmiAndBranch>(search_element);
   8887       if_isnumber.OrIf<HCompareMap>(
   8888           search_element, isolate()->factory()->heap_number_map());
   8889       if_isnumber.Then();
   8890       {
   8891         HValue* search_number =
   8892             AddUncasted<HForceRepresentation>(search_element,
   8893                                               Representation::Double());
   8894         LoopBuilder loop(this, context(), direction);
   8895         {
   8896           HValue* index = loop.BeginBody(initial, terminating, token);
   8897           HValue* element = AddUncasted<HLoadKeyed>(
   8898               elements, index, static_cast<HValue*>(NULL),
   8899               kind, ALLOW_RETURN_HOLE);
   8900 
   8901           IfBuilder if_element_isnumber(this);
   8902           if_element_isnumber.If<HIsSmiAndBranch>(element);
   8903           if_element_isnumber.OrIf<HCompareMap>(
   8904               element, isolate()->factory()->heap_number_map());
   8905           if_element_isnumber.Then();
   8906           {
   8907             HValue* number =
   8908                 AddUncasted<HForceRepresentation>(element,
   8909                                                   Representation::Double());
   8910             IfBuilder if_issame(this);
   8911             if_issame.If<HCompareNumericAndBranch>(
   8912                 number, search_number, Token::EQ_STRICT);
   8913             if_issame.Then();
   8914             {
   8915               Drop(1);
   8916               Push(index);
   8917               loop.Break();
   8918             }
   8919             if_issame.End();
   8920           }
   8921           if_element_isnumber.End();
   8922         }
   8923         loop.EndBody();
   8924       }
   8925       if_isnumber.Else();
   8926       {
   8927         LoopBuilder loop(this, context(), direction);
   8928         {
   8929           HValue* index = loop.BeginBody(initial, terminating, token);
   8930           HValue* element = AddUncasted<HLoadKeyed>(
   8931               elements, index, static_cast<HValue*>(NULL),
   8932               kind, ALLOW_RETURN_HOLE);
   8933           IfBuilder if_issame(this);
   8934           if_issame.If<HCompareObjectEqAndBranch>(
   8935               element, search_element);
   8936           if_issame.Then();
   8937           {
   8938             Drop(1);
   8939             Push(index);
   8940             loop.Break();
   8941           }
   8942           if_issame.End();
   8943         }
   8944         loop.EndBody();
   8945       }
   8946       if_isnumber.End();
   8947     }
   8948     if_isstring.End();
   8949   }
   8950 
   8951   return Pop();
   8952 }
   8953 
   8954 
   8955 bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
   8956   if (!array_function().is_identical_to(expr->target())) {
   8957     return false;
   8958   }
   8959 
   8960   Handle<AllocationSite> site = expr->allocation_site();
   8961   if (site.is_null()) return false;
   8962 
   8963   BuildArrayCall(expr,
   8964                  expr->arguments()->length(),
   8965                  function,
   8966                  site);
   8967   return true;
   8968 }
   8969 
   8970 
   8971 bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
   8972                                                    HValue* function) {
   8973   if (!array_function().is_identical_to(expr->target())) {
   8974     return false;
   8975   }
   8976 
   8977   BuildArrayCall(expr,
   8978                  expr->arguments()->length(),
   8979                  function,
   8980                  expr->allocation_site());
   8981   return true;
   8982 }
   8983 
   8984 
   8985 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
   8986   DCHECK(!HasStackOverflow());
   8987   DCHECK(current_block() != NULL);
   8988   DCHECK(current_block()->HasPredecessor());
   8989   Expression* callee = expr->expression();
   8990   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
   8991   HInstruction* call = NULL;
   8992 
   8993   Property* prop = callee->AsProperty();
   8994   if (prop != NULL) {
   8995     CHECK_ALIVE(VisitForValue(prop->obj()));
   8996     HValue* receiver = Top();
   8997 
   8998     SmallMapList* types;
   8999     ComputeReceiverTypes(expr, receiver, &types, zone());
   9000 
   9001     if (prop->key()->IsPropertyName() && types->length() > 0) {
   9002       Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
   9003       PropertyAccessInfo info(this, LOAD, ToType(types->first()), name);
   9004       if (!info.CanAccessAsMonomorphic(types)) {
   9005         HandlePolymorphicCallNamed(expr, receiver, types, name);
   9006         return;
   9007       }
   9008     }
   9009 
   9010     HValue* key = NULL;
   9011     if (!prop->key()->IsPropertyName()) {
   9012       CHECK_ALIVE(VisitForValue(prop->key()));
   9013       key = Pop();
   9014     }
   9015 
   9016     CHECK_ALIVE(PushLoad(prop, receiver, key));
   9017     HValue* function = Pop();
   9018 
   9019     if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
   9020 
   9021     // Push the function under the receiver.
   9022     environment()->SetExpressionStackAt(0, function);
   9023 
   9024     Push(receiver);
   9025 
   9026     if (function->IsConstant() &&
   9027         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9028       Handle<JSFunction> known_function = Handle<JSFunction>::cast(
   9029           HConstant::cast(function)->handle(isolate()));
   9030       expr->set_target(known_function);
   9031 
   9032       if (TryCallApply(expr)) return;
   9033       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9034 
   9035       Handle<Map> map = types->length() == 1 ? types->first() : Handle<Map>();
   9036       if (TryInlineBuiltinMethodCall(expr, receiver, map)) {
   9037         if (FLAG_trace_inlining) {
   9038           PrintF("Inlining builtin ");
   9039           known_function->ShortPrint();
   9040           PrintF("\n");
   9041         }
   9042         return;
   9043       }
   9044       if (TryInlineApiMethodCall(expr, receiver, types)) return;
   9045 
   9046       // Wrap the receiver if necessary.
   9047       if (NeedsWrappingFor(ToType(types->first()), known_function)) {
   9048         // Since HWrapReceiver currently cannot actually wrap numbers and
   9049         // strings, use the regular CallFunctionStub for method calls to wrap
   9050         // the receiver.
   9051         // TODO(verwaest): Support creation of value wrappers directly in
   9052         // HWrapReceiver.
   9053         call = New<HCallFunction>(
   9054             function, argument_count, WRAP_AND_CALL);
   9055       } else if (TryInlineCall(expr)) {
   9056         return;
   9057       } else {
   9058         call = BuildCallConstantFunction(known_function, argument_count);
   9059       }
   9060 
   9061     } else {
   9062       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9063       CallFunctionFlags flags = receiver->type().IsJSObject()
   9064           ? NO_CALL_FUNCTION_FLAGS : CALL_AS_METHOD;
   9065       call = New<HCallFunction>(function, argument_count, flags);
   9066     }
   9067     PushArgumentsFromEnvironment(argument_count);
   9068 
   9069   } else {
   9070     VariableProxy* proxy = expr->expression()->AsVariableProxy();
   9071     if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
   9072       return Bailout(kPossibleDirectCallToEval);
   9073     }
   9074 
   9075     // The function is on the stack in the unoptimized code during
   9076     // evaluation of the arguments.
   9077     CHECK_ALIVE(VisitForValue(expr->expression()));
   9078     HValue* function = Top();
   9079     if (expr->global_call()) {
   9080       Variable* var = proxy->var();
   9081       bool known_global_function = false;
   9082       // If there is a global property cell for the name at compile time and
   9083       // access check is not enabled we assume that the function will not change
   9084       // and generate optimized code for calling the function.
   9085       Handle<GlobalObject> global(current_info()->global_object());
   9086       LookupIterator it(global, var->name(),
   9087                         LookupIterator::OWN_SKIP_INTERCEPTOR);
   9088       GlobalPropertyAccess type = LookupGlobalProperty(var, &it, LOAD);
   9089       if (type == kUseCell) {
   9090         Handle<GlobalObject> global(current_info()->global_object());
   9091         known_global_function = expr->ComputeGlobalTarget(global, &it);
   9092       }
   9093       if (known_global_function) {
   9094         Add<HCheckValue>(function, expr->target());
   9095 
   9096         // Placeholder for the receiver.
   9097         Push(graph()->GetConstantUndefined());
   9098         CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9099 
   9100         // Patch the global object on the stack by the expected receiver.
   9101         HValue* receiver = ImplicitReceiverFor(function, expr->target());
   9102         const int receiver_index = argument_count - 1;
   9103         environment()->SetExpressionStackAt(receiver_index, receiver);
   9104 
   9105         if (TryInlineBuiltinFunctionCall(expr)) {
   9106           if (FLAG_trace_inlining) {
   9107             PrintF("Inlining builtin ");
   9108             expr->target()->ShortPrint();
   9109             PrintF("\n");
   9110           }
   9111           return;
   9112         }
   9113         if (TryInlineApiFunctionCall(expr, receiver)) return;
   9114         if (TryHandleArrayCall(expr, function)) return;
   9115         if (TryInlineCall(expr)) return;
   9116 
   9117         PushArgumentsFromEnvironment(argument_count);
   9118         call = BuildCallConstantFunction(expr->target(), argument_count);
   9119       } else {
   9120         Push(graph()->GetConstantUndefined());
   9121         CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9122         PushArgumentsFromEnvironment(argument_count);
   9123         call = New<HCallFunction>(function, argument_count);
   9124       }
   9125 
   9126     } else if (expr->IsMonomorphic()) {
   9127       Add<HCheckValue>(function, expr->target());
   9128 
   9129       Push(graph()->GetConstantUndefined());
   9130       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9131 
   9132       HValue* receiver = ImplicitReceiverFor(function, expr->target());
   9133       const int receiver_index = argument_count - 1;
   9134       environment()->SetExpressionStackAt(receiver_index, receiver);
   9135 
   9136       if (TryInlineBuiltinFunctionCall(expr)) {
   9137         if (FLAG_trace_inlining) {
   9138           PrintF("Inlining builtin ");
   9139           expr->target()->ShortPrint();
   9140           PrintF("\n");
   9141         }
   9142         return;
   9143       }
   9144       if (TryInlineApiFunctionCall(expr, receiver)) return;
   9145 
   9146       if (TryInlineCall(expr)) return;
   9147 
   9148       call = PreProcessCall(New<HInvokeFunction>(
   9149           function, expr->target(), argument_count));
   9150 
   9151     } else {
   9152       Push(graph()->GetConstantUndefined());
   9153       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9154       PushArgumentsFromEnvironment(argument_count);
   9155       call = New<HCallFunction>(function, argument_count);
   9156     }
   9157   }
   9158 
   9159   Drop(1);  // Drop the function.
   9160   return ast_context()->ReturnInstruction(call, expr->id());
   9161 }
   9162 
   9163 
   9164 void HOptimizedGraphBuilder::BuildInlinedCallArray(
   9165     Expression* expression,
   9166     int argument_count,
   9167     Handle<AllocationSite> site) {
   9168   DCHECK(!site.is_null());
   9169   DCHECK(argument_count >= 0 && argument_count <= 1);
   9170   NoObservableSideEffectsScope no_effects(this);
   9171 
   9172   // We should at least have the constructor on the expression stack.
   9173   HValue* constructor = environment()->ExpressionStackAt(argument_count);
   9174 
   9175   // Register on the site for deoptimization if the transition feedback changes.
   9176   AllocationSite::AddDependentCompilationInfo(
   9177       site, AllocationSite::TRANSITIONS, top_info());
   9178   ElementsKind kind = site->GetElementsKind();
   9179   HInstruction* site_instruction = Add<HConstant>(site);
   9180 
   9181   // In the single constant argument case, we may have to adjust elements kind
   9182   // to avoid creating a packed non-empty array.
   9183   if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
   9184     HValue* argument = environment()->Top();
   9185     if (argument->IsConstant()) {
   9186       HConstant* constant_argument = HConstant::cast(argument);
   9187       DCHECK(constant_argument->HasSmiValue());
   9188       int constant_array_size = constant_argument->Integer32Value();
   9189       if (constant_array_size != 0) {
   9190         kind = GetHoleyElementsKind(kind);
   9191       }
   9192     }
   9193   }
   9194 
   9195   // Build the array.
   9196   JSArrayBuilder array_builder(this,
   9197                                kind,
   9198                                site_instruction,
   9199                                constructor,
   9200                                DISABLE_ALLOCATION_SITES);
   9201   HValue* new_object = argument_count == 0
   9202       ? array_builder.AllocateEmptyArray()
   9203       : BuildAllocateArrayFromLength(&array_builder, Top());
   9204 
   9205   int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
   9206   Drop(args_to_drop);
   9207   ast_context()->ReturnValue(new_object);
   9208 }
   9209 
   9210 
   9211 // Checks whether allocation using the given constructor can be inlined.
   9212 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
   9213   return constructor->has_initial_map() &&
   9214       constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
   9215       constructor->initial_map()->instance_size() < HAllocate::kMaxInlineSize &&
   9216       constructor->initial_map()->InitialPropertiesLength() == 0;
   9217 }
   9218 
   9219 
   9220 bool HOptimizedGraphBuilder::IsCallArrayInlineable(
   9221     int argument_count,
   9222     Handle<AllocationSite> site) {
   9223   Handle<JSFunction> caller = current_info()->closure();
   9224   Handle<JSFunction> target = array_function();
   9225   // We should have the function plus array arguments on the environment stack.
   9226   DCHECK(environment()->length() >= (argument_count + 1));
   9227   DCHECK(!site.is_null());
   9228 
   9229   bool inline_ok = false;
   9230   if (site->CanInlineCall()) {
   9231     // We also want to avoid inlining in certain 1 argument scenarios.
   9232     if (argument_count == 1) {
   9233       HValue* argument = Top();
   9234       if (argument->IsConstant()) {
   9235         // Do not inline if the constant length argument is not a smi or
   9236         // outside the valid range for unrolled loop initialization.
   9237         HConstant* constant_argument = HConstant::cast(argument);
   9238         if (constant_argument->HasSmiValue()) {
   9239           int value = constant_argument->Integer32Value();
   9240           inline_ok = value >= 0 && value <= kElementLoopUnrollThreshold;
   9241           if (!inline_ok) {
   9242             TraceInline(target, caller,
   9243                         "Constant length outside of valid inlining range.");
   9244           }
   9245         }
   9246       } else {
   9247         TraceInline(target, caller,
   9248                     "Dont inline [new] Array(n) where n isn't constant.");
   9249       }
   9250     } else if (argument_count == 0) {
   9251       inline_ok = true;
   9252     } else {
   9253       TraceInline(target, caller, "Too many arguments to inline.");
   9254     }
   9255   } else {
   9256     TraceInline(target, caller, "AllocationSite requested no inlining.");
   9257   }
   9258 
   9259   if (inline_ok) {
   9260     TraceInline(target, caller, NULL);
   9261   }
   9262   return inline_ok;
   9263 }
   9264 
   9265 
   9266 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
   9267   DCHECK(!HasStackOverflow());
   9268   DCHECK(current_block() != NULL);
   9269   DCHECK(current_block()->HasPredecessor());
   9270   if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
   9271   int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
   9272   Factory* factory = isolate()->factory();
   9273 
   9274   // The constructor function is on the stack in the unoptimized code
   9275   // during evaluation of the arguments.
   9276   CHECK_ALIVE(VisitForValue(expr->expression()));
   9277   HValue* function = Top();
   9278   CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9279 
   9280   if (FLAG_inline_construct &&
   9281       expr->IsMonomorphic() &&
   9282       IsAllocationInlineable(expr->target())) {
   9283     Handle<JSFunction> constructor = expr->target();
   9284     HValue* check = Add<HCheckValue>(function, constructor);
   9285 
   9286     // Force completion of inobject slack tracking before generating
   9287     // allocation code to finalize instance size.
   9288     if (constructor->IsInobjectSlackTrackingInProgress()) {
   9289       constructor->CompleteInobjectSlackTracking();
   9290     }
   9291 
   9292     // Calculate instance size from initial map of constructor.
   9293     DCHECK(constructor->has_initial_map());
   9294     Handle<Map> initial_map(constructor->initial_map());
   9295     int instance_size = initial_map->instance_size();
   9296     DCHECK(initial_map->InitialPropertiesLength() == 0);
   9297 
   9298     // Allocate an instance of the implicit receiver object.
   9299     HValue* size_in_bytes = Add<HConstant>(instance_size);
   9300     HAllocationMode allocation_mode;
   9301     if (FLAG_pretenuring_call_new) {
   9302       if (FLAG_allocation_site_pretenuring) {
   9303         // Try to use pretenuring feedback.
   9304         Handle<AllocationSite> allocation_site = expr->allocation_site();
   9305         allocation_mode = HAllocationMode(allocation_site);
   9306         // Take a dependency on allocation site.
   9307         AllocationSite::AddDependentCompilationInfo(allocation_site,
   9308                                                     AllocationSite::TENURING,
   9309                                                     top_info());
   9310       }
   9311     }
   9312 
   9313     HAllocate* receiver = BuildAllocate(
   9314         size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
   9315     receiver->set_known_initial_map(initial_map);
   9316 
   9317     // Initialize map and fields of the newly allocated object.
   9318     { NoObservableSideEffectsScope no_effects(this);
   9319       DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE);
   9320       Add<HStoreNamedField>(receiver,
   9321           HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
   9322           Add<HConstant>(initial_map));
   9323       HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
   9324       Add<HStoreNamedField>(receiver,
   9325           HObjectAccess::ForMapAndOffset(initial_map,
   9326                                          JSObject::kPropertiesOffset),
   9327           empty_fixed_array);
   9328       Add<HStoreNamedField>(receiver,
   9329           HObjectAccess::ForMapAndOffset(initial_map,
   9330                                          JSObject::kElementsOffset),
   9331           empty_fixed_array);
   9332       if (initial_map->inobject_properties() != 0) {
   9333         HConstant* undefined = graph()->GetConstantUndefined();
   9334         for (int i = 0; i < initial_map->inobject_properties(); i++) {
   9335           int property_offset = initial_map->GetInObjectPropertyOffset(i);
   9336           Add<HStoreNamedField>(receiver,
   9337               HObjectAccess::ForMapAndOffset(initial_map, property_offset),
   9338               undefined);
   9339         }
   9340       }
   9341     }
   9342 
   9343     // Replace the constructor function with a newly allocated receiver using
   9344     // the index of the receiver from the top of the expression stack.
   9345     const int receiver_index = argument_count - 1;
   9346     DCHECK(environment()->ExpressionStackAt(receiver_index) == function);
   9347     environment()->SetExpressionStackAt(receiver_index, receiver);
   9348 
   9349     if (TryInlineConstruct(expr, receiver)) {
   9350       // Inlining worked, add a dependency on the initial map to make sure that
   9351       // this code is deoptimized whenever the initial map of the constructor
   9352       // changes.
   9353       Map::AddDependentCompilationInfo(
   9354           initial_map, DependentCode::kInitialMapChangedGroup, top_info());
   9355       return;
   9356     }
   9357 
   9358     // TODO(mstarzinger): For now we remove the previous HAllocate and all
   9359     // corresponding instructions and instead add HPushArguments for the
   9360     // arguments in case inlining failed.  What we actually should do is for
   9361     // inlining to try to build a subgraph without mutating the parent graph.
   9362     HInstruction* instr = current_block()->last();
   9363     do {
   9364       HInstruction* prev_instr = instr->previous();
   9365       instr->DeleteAndReplaceWith(NULL);
   9366       instr = prev_instr;
   9367     } while (instr != check);
   9368     environment()->SetExpressionStackAt(receiver_index, function);
   9369     HInstruction* call =
   9370       PreProcessCall(New<HCallNew>(function, argument_count));
   9371     return ast_context()->ReturnInstruction(call, expr->id());
   9372   } else {
   9373     // The constructor function is both an operand to the instruction and an
   9374     // argument to the construct call.
   9375     if (TryHandleArrayCallNew(expr, function)) return;
   9376 
   9377     HInstruction* call =
   9378         PreProcessCall(New<HCallNew>(function, argument_count));
   9379     return ast_context()->ReturnInstruction(call, expr->id());
   9380   }
   9381 }
   9382 
   9383 
   9384 // Support for generating inlined runtime functions.
   9385 
   9386 // Lookup table for generators for runtime calls that are generated inline.
   9387 // Elements of the table are member pointers to functions of
   9388 // HOptimizedGraphBuilder.
   9389 #define INLINE_FUNCTION_GENERATOR_ADDRESS(Name, argc, ressize)  \
   9390     &HOptimizedGraphBuilder::Generate##Name,
   9391 
   9392 const HOptimizedGraphBuilder::InlineFunctionGenerator
   9393     HOptimizedGraphBuilder::kInlineFunctionGenerators[] = {
   9394         INLINE_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
   9395         INLINE_OPTIMIZED_FUNCTION_LIST(INLINE_FUNCTION_GENERATOR_ADDRESS)
   9396 };
   9397 #undef INLINE_FUNCTION_GENERATOR_ADDRESS
   9398 
   9399 
   9400 template <class ViewClass>
   9401 void HGraphBuilder::BuildArrayBufferViewInitialization(
   9402     HValue* obj,
   9403     HValue* buffer,
   9404     HValue* byte_offset,
   9405     HValue* byte_length) {
   9406 
   9407   for (int offset = ViewClass::kSize;
   9408        offset < ViewClass::kSizeWithInternalFields;
   9409        offset += kPointerSize) {
   9410     Add<HStoreNamedField>(obj,
   9411         HObjectAccess::ForObservableJSObjectOffset(offset),
   9412         graph()->GetConstant0());
   9413   }
   9414 
   9415   Add<HStoreNamedField>(
   9416       obj,
   9417       HObjectAccess::ForJSArrayBufferViewByteOffset(),
   9418       byte_offset);
   9419   Add<HStoreNamedField>(
   9420       obj,
   9421       HObjectAccess::ForJSArrayBufferViewByteLength(),
   9422       byte_length);
   9423 
   9424   if (buffer != NULL) {
   9425     Add<HStoreNamedField>(
   9426         obj,
   9427         HObjectAccess::ForJSArrayBufferViewBuffer(), buffer);
   9428     HObjectAccess weak_first_view_access =
   9429         HObjectAccess::ForJSArrayBufferWeakFirstView();
   9430     Add<HStoreNamedField>(obj,
   9431         HObjectAccess::ForJSArrayBufferViewWeakNext(),
   9432         Add<HLoadNamedField>(buffer,
   9433                              static_cast<HValue*>(NULL),
   9434                              weak_first_view_access));
   9435     Add<HStoreNamedField>(buffer, weak_first_view_access, obj);
   9436   } else {
   9437     Add<HStoreNamedField>(
   9438         obj,
   9439         HObjectAccess::ForJSArrayBufferViewBuffer(),
   9440         Add<HConstant>(static_cast<int32_t>(0)));
   9441     Add<HStoreNamedField>(obj,
   9442         HObjectAccess::ForJSArrayBufferViewWeakNext(),
   9443         graph()->GetConstantUndefined());
   9444   }
   9445 }
   9446 
   9447 
   9448 void HOptimizedGraphBuilder::GenerateDataViewInitialize(
   9449     CallRuntime* expr) {
   9450   ZoneList<Expression*>* arguments = expr->arguments();
   9451 
   9452   DCHECK(arguments->length()== 4);
   9453   CHECK_ALIVE(VisitForValue(arguments->at(0)));
   9454   HValue* obj = Pop();
   9455 
   9456   CHECK_ALIVE(VisitForValue(arguments->at(1)));
   9457   HValue* buffer = Pop();
   9458 
   9459   CHECK_ALIVE(VisitForValue(arguments->at(2)));
   9460   HValue* byte_offset = Pop();
   9461 
   9462   CHECK_ALIVE(VisitForValue(arguments->at(3)));
   9463   HValue* byte_length = Pop();
   9464 
   9465   {
   9466     NoObservableSideEffectsScope scope(this);
   9467     BuildArrayBufferViewInitialization<JSDataView>(
   9468         obj, buffer, byte_offset, byte_length);
   9469   }
   9470 }
   9471 
   9472 
   9473 static Handle<Map> TypedArrayMap(Isolate* isolate,
   9474                                  ExternalArrayType array_type,
   9475                                  ElementsKind target_kind) {
   9476   Handle<Context> native_context = isolate->native_context();
   9477   Handle<JSFunction> fun;
   9478   switch (array_type) {
   9479 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size)                       \
   9480     case kExternal##Type##Array:                                              \
   9481       fun = Handle<JSFunction>(native_context->type##_array_fun());           \
   9482       break;
   9483 
   9484     TYPED_ARRAYS(TYPED_ARRAY_CASE)
   9485 #undef TYPED_ARRAY_CASE
   9486   }
   9487   Handle<Map> map(fun->initial_map());
   9488   return Map::AsElementsKind(map, target_kind);
   9489 }
   9490 
   9491 
   9492 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
   9493     ExternalArrayType array_type,
   9494     bool is_zero_byte_offset,
   9495     HValue* buffer, HValue* byte_offset, HValue* length) {
   9496   Handle<Map> external_array_map(
   9497       isolate()->heap()->MapForExternalArrayType(array_type));
   9498 
   9499   // The HForceRepresentation is to prevent possible deopt on int-smi
   9500   // conversion after allocation but before the new object fields are set.
   9501   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   9502   HValue* elements =
   9503       Add<HAllocate>(
   9504           Add<HConstant>(ExternalArray::kAlignedSize),
   9505           HType::HeapObject(),
   9506           NOT_TENURED,
   9507           external_array_map->instance_type());
   9508 
   9509   AddStoreMapConstant(elements, external_array_map);
   9510   Add<HStoreNamedField>(elements,
   9511       HObjectAccess::ForFixedArrayLength(), length);
   9512 
   9513   HValue* backing_store = Add<HLoadNamedField>(
   9514       buffer, static_cast<HValue*>(NULL),
   9515       HObjectAccess::ForJSArrayBufferBackingStore());
   9516 
   9517   HValue* typed_array_start;
   9518   if (is_zero_byte_offset) {
   9519     typed_array_start = backing_store;
   9520   } else {
   9521     HInstruction* external_pointer =
   9522         AddUncasted<HAdd>(backing_store, byte_offset);
   9523     // Arguments are checked prior to call to TypedArrayInitialize,
   9524     // including byte_offset.
   9525     external_pointer->ClearFlag(HValue::kCanOverflow);
   9526     typed_array_start = external_pointer;
   9527   }
   9528 
   9529   Add<HStoreNamedField>(elements,
   9530       HObjectAccess::ForExternalArrayExternalPointer(),
   9531       typed_array_start);
   9532 
   9533   return elements;
   9534 }
   9535 
   9536 
   9537 HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
   9538     ExternalArrayType array_type, size_t element_size,
   9539     ElementsKind fixed_elements_kind,
   9540     HValue* byte_length, HValue* length) {
   9541   STATIC_ASSERT(
   9542       (FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
   9543   HValue* total_size;
   9544 
   9545   // if fixed array's elements are not aligned to object's alignment,
   9546   // we need to align the whole array to object alignment.
   9547   if (element_size % kObjectAlignment != 0) {
   9548     total_size = BuildObjectSizeAlignment(
   9549         byte_length, FixedTypedArrayBase::kHeaderSize);
   9550   } else {
   9551     total_size = AddUncasted<HAdd>(byte_length,
   9552         Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
   9553     total_size->ClearFlag(HValue::kCanOverflow);
   9554   }
   9555 
   9556   // The HForceRepresentation is to prevent possible deopt on int-smi
   9557   // conversion after allocation but before the new object fields are set.
   9558   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   9559   Handle<Map> fixed_typed_array_map(
   9560       isolate()->heap()->MapForFixedTypedArray(array_type));
   9561   HValue* elements =
   9562       Add<HAllocate>(total_size, HType::HeapObject(),
   9563                      NOT_TENURED, fixed_typed_array_map->instance_type());
   9564   AddStoreMapConstant(elements, fixed_typed_array_map);
   9565 
   9566   Add<HStoreNamedField>(elements,
   9567       HObjectAccess::ForFixedArrayLength(),
   9568       length);
   9569 
   9570   HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
   9571 
   9572   {
   9573     LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
   9574 
   9575     HValue* key = builder.BeginBody(
   9576         Add<HConstant>(static_cast<int32_t>(0)),
   9577         length, Token::LT);
   9578     Add<HStoreKeyed>(elements, key, filler, fixed_elements_kind);
   9579 
   9580     builder.EndBody();
   9581   }
   9582   return elements;
   9583 }
   9584 
   9585 
   9586 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
   9587     CallRuntime* expr) {
   9588   ZoneList<Expression*>* arguments = expr->arguments();
   9589 
   9590   static const int kObjectArg = 0;
   9591   static const int kArrayIdArg = 1;
   9592   static const int kBufferArg = 2;
   9593   static const int kByteOffsetArg = 3;
   9594   static const int kByteLengthArg = 4;
   9595   static const int kArgsLength = 5;
   9596   DCHECK(arguments->length() == kArgsLength);
   9597 
   9598 
   9599   CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
   9600   HValue* obj = Pop();
   9601 
   9602   if (arguments->at(kArrayIdArg)->IsLiteral()) {
   9603     // This should never happen in real use, but can happen when fuzzing.
   9604     // Just bail out.
   9605     Bailout(kNeedSmiLiteral);
   9606     return;
   9607   }
   9608   Handle<Object> value =
   9609       static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
   9610   if (!value->IsSmi()) {
   9611     // This should never happen in real use, but can happen when fuzzing.
   9612     // Just bail out.
   9613     Bailout(kNeedSmiLiteral);
   9614     return;
   9615   }
   9616   int array_id = Smi::cast(*value)->value();
   9617 
   9618   HValue* buffer;
   9619   if (!arguments->at(kBufferArg)->IsNullLiteral()) {
   9620     CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
   9621     buffer = Pop();
   9622   } else {
   9623     buffer = NULL;
   9624   }
   9625 
   9626   HValue* byte_offset;
   9627   bool is_zero_byte_offset;
   9628 
   9629   if (arguments->at(kByteOffsetArg)->IsLiteral()
   9630       && Smi::FromInt(0) ==
   9631       *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
   9632     byte_offset = Add<HConstant>(static_cast<int32_t>(0));
   9633     is_zero_byte_offset = true;
   9634   } else {
   9635     CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
   9636     byte_offset = Pop();
   9637     is_zero_byte_offset = false;
   9638     DCHECK(buffer != NULL);
   9639   }
   9640 
   9641   CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
   9642   HValue* byte_length = Pop();
   9643 
   9644   NoObservableSideEffectsScope scope(this);
   9645   IfBuilder byte_offset_smi(this);
   9646 
   9647   if (!is_zero_byte_offset) {
   9648     byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
   9649     byte_offset_smi.Then();
   9650   }
   9651 
   9652   ExternalArrayType array_type =
   9653       kExternalInt8Array;  // Bogus initialization.
   9654   size_t element_size = 1;  // Bogus initialization.
   9655   ElementsKind external_elements_kind =  // Bogus initialization.
   9656       EXTERNAL_INT8_ELEMENTS;
   9657   ElementsKind fixed_elements_kind =  // Bogus initialization.
   9658       INT8_ELEMENTS;
   9659   Runtime::ArrayIdToTypeAndSize(array_id,
   9660       &array_type,
   9661       &external_elements_kind,
   9662       &fixed_elements_kind,
   9663       &element_size);
   9664 
   9665 
   9666   { //  byte_offset is Smi.
   9667     BuildArrayBufferViewInitialization<JSTypedArray>(
   9668         obj, buffer, byte_offset, byte_length);
   9669 
   9670 
   9671     HInstruction* length = AddUncasted<HDiv>(byte_length,
   9672         Add<HConstant>(static_cast<int32_t>(element_size)));
   9673 
   9674     Add<HStoreNamedField>(obj,
   9675         HObjectAccess::ForJSTypedArrayLength(),
   9676         length);
   9677 
   9678     HValue* elements;
   9679     if (buffer != NULL) {
   9680       elements = BuildAllocateExternalElements(
   9681           array_type, is_zero_byte_offset, buffer, byte_offset, length);
   9682       Handle<Map> obj_map = TypedArrayMap(
   9683           isolate(), array_type, external_elements_kind);
   9684       AddStoreMapConstant(obj, obj_map);
   9685     } else {
   9686       DCHECK(is_zero_byte_offset);
   9687       elements = BuildAllocateFixedTypedArray(
   9688           array_type, element_size, fixed_elements_kind,
   9689           byte_length, length);
   9690     }
   9691     Add<HStoreNamedField>(
   9692         obj, HObjectAccess::ForElementsPointer(), elements);
   9693   }
   9694 
   9695   if (!is_zero_byte_offset) {
   9696     byte_offset_smi.Else();
   9697     { //  byte_offset is not Smi.
   9698       Push(obj);
   9699       CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg)));
   9700       Push(buffer);
   9701       Push(byte_offset);
   9702       Push(byte_length);
   9703       PushArgumentsFromEnvironment(kArgsLength);
   9704       Add<HCallRuntime>(expr->name(), expr->function(), kArgsLength);
   9705     }
   9706   }
   9707   byte_offset_smi.End();
   9708 }
   9709 
   9710 
   9711 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
   9712   DCHECK(expr->arguments()->length() == 0);
   9713   HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
   9714   return ast_context()->ReturnInstruction(max_smi, expr->id());
   9715 }
   9716 
   9717 
   9718 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
   9719     CallRuntime* expr) {
   9720   DCHECK(expr->arguments()->length() == 0);
   9721   HConstant* result = New<HConstant>(static_cast<int32_t>(
   9722         FLAG_typed_array_max_size_in_heap));
   9723   return ast_context()->ReturnInstruction(result, expr->id());
   9724 }
   9725 
   9726 
   9727 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
   9728     CallRuntime* expr) {
   9729   DCHECK(expr->arguments()->length() == 1);
   9730   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   9731   HValue* buffer = Pop();
   9732   HInstruction* result = New<HLoadNamedField>(
   9733     buffer,
   9734     static_cast<HValue*>(NULL),
   9735     HObjectAccess::ForJSArrayBufferByteLength());
   9736   return ast_context()->ReturnInstruction(result, expr->id());
   9737 }
   9738 
   9739 
   9740 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
   9741     CallRuntime* expr) {
   9742   DCHECK(expr->arguments()->length() == 1);
   9743   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   9744   HValue* buffer = Pop();
   9745   HInstruction* result = New<HLoadNamedField>(
   9746     buffer,
   9747     static_cast<HValue*>(NULL),
   9748     HObjectAccess::ForJSArrayBufferViewByteLength());
   9749   return ast_context()->ReturnInstruction(result, expr->id());
   9750 }
   9751 
   9752 
   9753 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
   9754     CallRuntime* expr) {
   9755   DCHECK(expr->arguments()->length() == 1);
   9756   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   9757   HValue* buffer = Pop();
   9758   HInstruction* result = New<HLoadNamedField>(
   9759     buffer,
   9760     static_cast<HValue*>(NULL),
   9761     HObjectAccess::ForJSArrayBufferViewByteOffset());
   9762   return ast_context()->ReturnInstruction(result, expr->id());
   9763 }
   9764 
   9765 
   9766 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
   9767     CallRuntime* expr) {
   9768   DCHECK(expr->arguments()->length() == 1);
   9769   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   9770   HValue* buffer = Pop();
   9771   HInstruction* result = New<HLoadNamedField>(
   9772     buffer,
   9773     static_cast<HValue*>(NULL),
   9774     HObjectAccess::ForJSTypedArrayLength());
   9775   return ast_context()->ReturnInstruction(result, expr->id());
   9776 }
   9777 
   9778 
   9779 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
   9780   DCHECK(!HasStackOverflow());
   9781   DCHECK(current_block() != NULL);
   9782   DCHECK(current_block()->HasPredecessor());
   9783   if (expr->is_jsruntime()) {
   9784     return Bailout(kCallToAJavaScriptRuntimeFunction);
   9785   }
   9786 
   9787   const Runtime::Function* function = expr->function();
   9788   DCHECK(function != NULL);
   9789 
   9790   if (function->intrinsic_type == Runtime::INLINE ||
   9791       function->intrinsic_type == Runtime::INLINE_OPTIMIZED) {
   9792     DCHECK(expr->name()->length() > 0);
   9793     DCHECK(expr->name()->Get(0) == '_');
   9794     // Call to an inline function.
   9795     int lookup_index = static_cast<int>(function->function_id) -
   9796         static_cast<int>(Runtime::kFirstInlineFunction);
   9797     DCHECK(lookup_index >= 0);
   9798     DCHECK(static_cast<size_t>(lookup_index) <
   9799            arraysize(kInlineFunctionGenerators));
   9800     InlineFunctionGenerator generator = kInlineFunctionGenerators[lookup_index];
   9801 
   9802     // Call the inline code generator using the pointer-to-member.
   9803     (this->*generator)(expr);
   9804   } else {
   9805     DCHECK(function->intrinsic_type == Runtime::RUNTIME);
   9806     Handle<String> name = expr->name();
   9807     int argument_count = expr->arguments()->length();
   9808     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9809     PushArgumentsFromEnvironment(argument_count);
   9810     HCallRuntime* call = New<HCallRuntime>(name, function,
   9811                                            argument_count);
   9812     return ast_context()->ReturnInstruction(call, expr->id());
   9813   }
   9814 }
   9815 
   9816 
   9817 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
   9818   DCHECK(!HasStackOverflow());
   9819   DCHECK(current_block() != NULL);
   9820   DCHECK(current_block()->HasPredecessor());
   9821   switch (expr->op()) {
   9822     case Token::DELETE: return VisitDelete(expr);
   9823     case Token::VOID: return VisitVoid(expr);
   9824     case Token::TYPEOF: return VisitTypeof(expr);
   9825     case Token::NOT: return VisitNot(expr);
   9826     default: UNREACHABLE();
   9827   }
   9828 }
   9829 
   9830 
   9831 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
   9832   Property* prop = expr->expression()->AsProperty();
   9833   VariableProxy* proxy = expr->expression()->AsVariableProxy();
   9834   if (prop != NULL) {
   9835     CHECK_ALIVE(VisitForValue(prop->obj()));
   9836     CHECK_ALIVE(VisitForValue(prop->key()));
   9837     HValue* key = Pop();
   9838     HValue* obj = Pop();
   9839     HValue* function = AddLoadJSBuiltin(Builtins::DELETE);
   9840     Add<HPushArguments>(obj, key, Add<HConstant>(function_strict_mode()));
   9841     // TODO(olivf) InvokeFunction produces a check for the parameter count,
   9842     // even though we are certain to pass the correct number of arguments here.
   9843     HInstruction* instr = New<HInvokeFunction>(function, 3);
   9844     return ast_context()->ReturnInstruction(instr, expr->id());
   9845   } else if (proxy != NULL) {
   9846     Variable* var = proxy->var();
   9847     if (var->IsUnallocated()) {
   9848       Bailout(kDeleteWithGlobalVariable);
   9849     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
   9850       // Result of deleting non-global variables is false.  'this' is not
   9851       // really a variable, though we implement it as one.  The
   9852       // subexpression does not have side effects.
   9853       HValue* value = var->is_this()
   9854           ? graph()->GetConstantTrue()
   9855           : graph()->GetConstantFalse();
   9856       return ast_context()->ReturnValue(value);
   9857     } else {
   9858       Bailout(kDeleteWithNonGlobalVariable);
   9859     }
   9860   } else {
   9861     // Result of deleting non-property, non-variable reference is true.
   9862     // Evaluate the subexpression for side effects.
   9863     CHECK_ALIVE(VisitForEffect(expr->expression()));
   9864     return ast_context()->ReturnValue(graph()->GetConstantTrue());
   9865   }
   9866 }
   9867 
   9868 
   9869 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
   9870   CHECK_ALIVE(VisitForEffect(expr->expression()));
   9871   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   9872 }
   9873 
   9874 
   9875 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
   9876   CHECK_ALIVE(VisitForTypeOf(expr->expression()));
   9877   HValue* value = Pop();
   9878   HInstruction* instr = New<HTypeof>(value);
   9879   return ast_context()->ReturnInstruction(instr, expr->id());
   9880 }
   9881 
   9882 
   9883 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
   9884   if (ast_context()->IsTest()) {
   9885     TestContext* context = TestContext::cast(ast_context());
   9886     VisitForControl(expr->expression(),
   9887                     context->if_false(),
   9888                     context->if_true());
   9889     return;
   9890   }
   9891 
   9892   if (ast_context()->IsEffect()) {
   9893     VisitForEffect(expr->expression());
   9894     return;
   9895   }
   9896 
   9897   DCHECK(ast_context()->IsValue());
   9898   HBasicBlock* materialize_false = graph()->CreateBasicBlock();
   9899   HBasicBlock* materialize_true = graph()->CreateBasicBlock();
   9900   CHECK_BAILOUT(VisitForControl(expr->expression(),
   9901                                 materialize_false,
   9902                                 materialize_true));
   9903 
   9904   if (materialize_false->HasPredecessor()) {
   9905     materialize_false->SetJoinId(expr->MaterializeFalseId());
   9906     set_current_block(materialize_false);
   9907     Push(graph()->GetConstantFalse());
   9908   } else {
   9909     materialize_false = NULL;
   9910   }
   9911 
   9912   if (materialize_true->HasPredecessor()) {
   9913     materialize_true->SetJoinId(expr->MaterializeTrueId());
   9914     set_current_block(materialize_true);
   9915     Push(graph()->GetConstantTrue());
   9916   } else {
   9917     materialize_true = NULL;
   9918   }
   9919 
   9920   HBasicBlock* join =
   9921     CreateJoin(materialize_false, materialize_true, expr->id());
   9922   set_current_block(join);
   9923   if (join != NULL) return ast_context()->ReturnValue(Pop());
   9924 }
   9925 
   9926 
   9927 HInstruction* HOptimizedGraphBuilder::BuildIncrement(
   9928     bool returns_original_input,
   9929     CountOperation* expr) {
   9930   // The input to the count operation is on top of the expression stack.
   9931   Representation rep = Representation::FromType(expr->type());
   9932   if (rep.IsNone() || rep.IsTagged()) {
   9933     rep = Representation::Smi();
   9934   }
   9935 
   9936   if (returns_original_input) {
   9937     // We need an explicit HValue representing ToNumber(input).  The
   9938     // actual HChange instruction we need is (sometimes) added in a later
   9939     // phase, so it is not available now to be used as an input to HAdd and
   9940     // as the return value.
   9941     HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
   9942     if (!rep.IsDouble()) {
   9943       number_input->SetFlag(HInstruction::kFlexibleRepresentation);
   9944       number_input->SetFlag(HInstruction::kCannotBeTagged);
   9945     }
   9946     Push(number_input);
   9947   }
   9948 
   9949   // The addition has no side effects, so we do not need
   9950   // to simulate the expression stack after this instruction.
   9951   // Any later failures deopt to the load of the input or earlier.
   9952   HConstant* delta = (expr->op() == Token::INC)
   9953       ? graph()->GetConstant1()
   9954       : graph()->GetConstantMinus1();
   9955   HInstruction* instr = AddUncasted<HAdd>(Top(), delta);
   9956   if (instr->IsAdd()) {
   9957     HAdd* add = HAdd::cast(instr);
   9958     add->set_observed_input_representation(1, rep);
   9959     add->set_observed_input_representation(2, Representation::Smi());
   9960   }
   9961   instr->SetFlag(HInstruction::kCannotBeTagged);
   9962   instr->ClearAllSideEffects();
   9963   return instr;
   9964 }
   9965 
   9966 
   9967 void HOptimizedGraphBuilder::BuildStoreForEffect(Expression* expr,
   9968                                                  Property* prop,
   9969                                                  BailoutId ast_id,
   9970                                                  BailoutId return_id,
   9971                                                  HValue* object,
   9972                                                  HValue* key,
   9973                                                  HValue* value) {
   9974   EffectContext for_effect(this);
   9975   Push(object);
   9976   if (key != NULL) Push(key);
   9977   Push(value);
   9978   BuildStore(expr, prop, ast_id, return_id);
   9979 }
   9980 
   9981 
   9982 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
   9983   DCHECK(!HasStackOverflow());
   9984   DCHECK(current_block() != NULL);
   9985   DCHECK(current_block()->HasPredecessor());
   9986   if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
   9987   Expression* target = expr->expression();
   9988   VariableProxy* proxy = target->AsVariableProxy();
   9989   Property* prop = target->AsProperty();
   9990   if (proxy == NULL && prop == NULL) {
   9991     return Bailout(kInvalidLhsInCountOperation);
   9992   }
   9993 
   9994   // Match the full code generator stack by simulating an extra stack
   9995   // element for postfix operations in a non-effect context.  The return
   9996   // value is ToNumber(input).
   9997   bool returns_original_input =
   9998       expr->is_postfix() && !ast_context()->IsEffect();
   9999   HValue* input = NULL;  // ToNumber(original_input).
   10000   HValue* after = NULL;  // The result after incrementing or decrementing.
   10001 
   10002   if (proxy != NULL) {
   10003     Variable* var = proxy->var();
   10004     if (var->mode() == CONST_LEGACY)  {
   10005       return Bailout(kUnsupportedCountOperationWithConst);
   10006     }
   10007     // Argument of the count operation is a variable, not a property.
   10008     DCHECK(prop == NULL);
   10009     CHECK_ALIVE(VisitForValue(target));
   10010 
   10011     after = BuildIncrement(returns_original_input, expr);
   10012     input = returns_original_input ? Top() : Pop();
   10013     Push(after);
   10014 
   10015     switch (var->location()) {
   10016       case Variable::UNALLOCATED:
   10017         HandleGlobalVariableAssignment(var,
   10018                                        after,
   10019                                        expr->AssignmentId());
   10020         break;
   10021 
   10022       case Variable::PARAMETER:
   10023       case Variable::LOCAL:
   10024         BindIfLive(var, after);
   10025         break;
   10026 
   10027       case Variable::CONTEXT: {
   10028         // Bail out if we try to mutate a parameter value in a function
   10029         // using the arguments object.  We do not (yet) correctly handle the
   10030         // arguments property of the function.
   10031         if (current_info()->scope()->arguments() != NULL) {
   10032           // Parameters will rewrite to context slots.  We have no direct
   10033           // way to detect that the variable is a parameter so we use a
   10034           // linear search of the parameter list.
   10035           int count = current_info()->scope()->num_parameters();
   10036           for (int i = 0; i < count; ++i) {
   10037             if (var == current_info()->scope()->parameter(i)) {
   10038               return Bailout(kAssignmentToParameterInArgumentsObject);
   10039             }
   10040           }
   10041         }
   10042 
   10043         HValue* context = BuildContextChainWalk(var);
   10044         HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
   10045             ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
   10046         HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
   10047                                                           mode, after);
   10048         if (instr->HasObservableSideEffects()) {
   10049           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   10050         }
   10051         break;
   10052       }
   10053 
   10054       case Variable::LOOKUP:
   10055         return Bailout(kLookupVariableInCountOperation);
   10056     }
   10057 
   10058     Drop(returns_original_input ? 2 : 1);
   10059     return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
   10060   }
   10061 
   10062   // Argument of the count operation is a property.
   10063   DCHECK(prop != NULL);
   10064   if (returns_original_input) Push(graph()->GetConstantUndefined());
   10065 
   10066   CHECK_ALIVE(VisitForValue(prop->obj()));
   10067   HValue* object = Top();
   10068 
   10069   HValue* key = NULL;
   10070   if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
   10071     CHECK_ALIVE(VisitForValue(prop->key()));
   10072     key = Top();
   10073   }
   10074 
   10075   CHECK_ALIVE(PushLoad(prop, object, key));
   10076 
   10077   after = BuildIncrement(returns_original_input, expr);
   10078 
   10079   if (returns_original_input) {
   10080     input = Pop();
   10081     // Drop object and key to push it again in the effect context below.
   10082     Drop(key == NULL ? 1 : 2);
   10083     environment()->SetExpressionStackAt(0, input);
   10084     CHECK_ALIVE(BuildStoreForEffect(
   10085         expr, prop, expr->id(), expr->AssignmentId(), object, key, after));
   10086     return ast_context()->ReturnValue(Pop());
   10087   }
   10088 
   10089   environment()->SetExpressionStackAt(0, after);
   10090   return BuildStore(expr, prop, expr->id(), expr->AssignmentId());
   10091 }
   10092 
   10093 
   10094 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
   10095     HValue* string,
   10096     HValue* index) {
   10097   if (string->IsConstant() && index->IsConstant()) {
   10098     HConstant* c_string = HConstant::cast(string);
   10099     HConstant* c_index = HConstant::cast(index);
   10100     if (c_string->HasStringValue() && c_index->HasNumberValue()) {
   10101       int32_t i = c_index->NumberValueAsInteger32();
   10102       Handle<String> s = c_string->StringValue();
   10103       if (i < 0 || i >= s->length()) {
   10104         return New<HConstant>(base::OS::nan_value());
   10105       }
   10106       return New<HConstant>(s->Get(i));
   10107     }
   10108   }
   10109   string = BuildCheckString(string);
   10110   index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
   10111   return New<HStringCharCodeAt>(string, index);
   10112 }
   10113 
   10114 
   10115 // Checks if the given shift amounts have following forms:
   10116 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
   10117 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
   10118                                              HValue* const32_minus_sa) {
   10119   if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
   10120     const HConstant* c1 = HConstant::cast(sa);
   10121     const HConstant* c2 = HConstant::cast(const32_minus_sa);
   10122     return c1->HasInteger32Value() && c2->HasInteger32Value() &&
   10123         (c1->Integer32Value() + c2->Integer32Value() == 32);
   10124   }
   10125   if (!const32_minus_sa->IsSub()) return false;
   10126   HSub* sub = HSub::cast(const32_minus_sa);
   10127   return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
   10128 }
   10129 
   10130 
   10131 // Checks if the left and the right are shift instructions with the oposite
   10132 // directions that can be replaced by one rotate right instruction or not.
   10133 // Returns the operand and the shift amount for the rotate instruction in the
   10134 // former case.
   10135 bool HGraphBuilder::MatchRotateRight(HValue* left,
   10136                                      HValue* right,
   10137                                      HValue** operand,
   10138                                      HValue** shift_amount) {
   10139   HShl* shl;
   10140   HShr* shr;
   10141   if (left->IsShl() && right->IsShr()) {
   10142     shl = HShl::cast(left);
   10143     shr = HShr::cast(right);
   10144   } else if (left->IsShr() && right->IsShl()) {
   10145     shl = HShl::cast(right);
   10146     shr = HShr::cast(left);
   10147   } else {
   10148     return false;
   10149   }
   10150   if (shl->left() != shr->left()) return false;
   10151 
   10152   if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
   10153       !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
   10154     return false;
   10155   }
   10156   *operand= shr->left();
   10157   *shift_amount = shr->right();
   10158   return true;
   10159 }
   10160 
   10161 
   10162 bool CanBeZero(HValue* right) {
   10163   if (right->IsConstant()) {
   10164     HConstant* right_const = HConstant::cast(right);
   10165     if (right_const->HasInteger32Value() &&
   10166        (right_const->Integer32Value() & 0x1f) != 0) {
   10167       return false;
   10168     }
   10169   }
   10170   return true;
   10171 }
   10172 
   10173 
   10174 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
   10175                                          Type* expected) {
   10176   if (expected->Is(Type::SignedSmall())) {
   10177     return AddUncasted<HForceRepresentation>(number, Representation::Smi());
   10178   }
   10179   if (expected->Is(Type::Signed32())) {
   10180     return AddUncasted<HForceRepresentation>(number,
   10181                                              Representation::Integer32());
   10182   }
   10183   return number;
   10184 }
   10185 
   10186 
   10187 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
   10188   if (value->IsConstant()) {
   10189     HConstant* constant = HConstant::cast(value);
   10190     Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone());
   10191     if (number.has_value) {
   10192       *expected = Type::Number(zone());
   10193       return AddInstruction(number.value);
   10194     }
   10195   }
   10196 
   10197   // We put temporary values on the stack, which don't correspond to anything
   10198   // in baseline code. Since nothing is observable we avoid recording those
   10199   // pushes with a NoObservableSideEffectsScope.
   10200   NoObservableSideEffectsScope no_effects(this);
   10201 
   10202   Type* expected_type = *expected;
   10203 
   10204   // Separate the number type from the rest.
   10205   Type* expected_obj =
   10206       Type::Intersect(expected_type, Type::NonNumber(zone()), zone());
   10207   Type* expected_number =
   10208       Type::Intersect(expected_type, Type::Number(zone()), zone());
   10209 
   10210   // We expect to get a number.
   10211   // (We need to check first, since Type::None->Is(Type::Any()) == true.
   10212   if (expected_obj->Is(Type::None())) {
   10213     DCHECK(!expected_number->Is(Type::None(zone())));
   10214     return value;
   10215   }
   10216 
   10217   if (expected_obj->Is(Type::Undefined(zone()))) {
   10218     // This is already done by HChange.
   10219     *expected = Type::Union(expected_number, Type::Number(zone()), zone());
   10220     return value;
   10221   }
   10222 
   10223   return value;
   10224 }
   10225 
   10226 
   10227 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
   10228     BinaryOperation* expr,
   10229     HValue* left,
   10230     HValue* right,
   10231     PushBeforeSimulateBehavior push_sim_result) {
   10232   Type* left_type = expr->left()->bounds().lower;
   10233   Type* right_type = expr->right()->bounds().lower;
   10234   Type* result_type = expr->bounds().lower;
   10235   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
   10236   Handle<AllocationSite> allocation_site = expr->allocation_site();
   10237 
   10238   HAllocationMode allocation_mode;
   10239   if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
   10240     allocation_mode = HAllocationMode(allocation_site);
   10241   }
   10242 
   10243   HValue* result = HGraphBuilder::BuildBinaryOperation(
   10244       expr->op(), left, right, left_type, right_type, result_type,
   10245       fixed_right_arg, allocation_mode);
   10246   // Add a simulate after instructions with observable side effects, and
   10247   // after phis, which are the result of BuildBinaryOperation when we
   10248   // inlined some complex subgraph.
   10249   if (result->HasObservableSideEffects() || result->IsPhi()) {
   10250     if (push_sim_result == PUSH_BEFORE_SIMULATE) {
   10251       Push(result);
   10252       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   10253       Drop(1);
   10254     } else {
   10255       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   10256     }
   10257   }
   10258   return result;
   10259 }
   10260 
   10261 
   10262 HValue* HGraphBuilder::BuildBinaryOperation(
   10263     Token::Value op,
   10264     HValue* left,
   10265     HValue* right,
   10266     Type* left_type,
   10267     Type* right_type,
   10268     Type* result_type,
   10269     Maybe<int> fixed_right_arg,
   10270     HAllocationMode allocation_mode) {
   10271 
   10272   Representation left_rep = Representation::FromType(left_type);
   10273   Representation right_rep = Representation::FromType(right_type);
   10274 
   10275   bool maybe_string_add = op == Token::ADD &&
   10276                           (left_type->Maybe(Type::String()) ||
   10277                            left_type->Maybe(Type::Receiver()) ||
   10278                            right_type->Maybe(Type::String()) ||
   10279                            right_type->Maybe(Type::Receiver()));
   10280 
   10281   if (!left_type->IsInhabited()) {
   10282     Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation",
   10283                      Deoptimizer::SOFT);
   10284     // TODO(rossberg): we should be able to get rid of non-continuous
   10285     // defaults.
   10286     left_type = Type::Any(zone());
   10287   } else {
   10288     if (!maybe_string_add) left = TruncateToNumber(left, &left_type);
   10289     left_rep = Representation::FromType(left_type);
   10290   }
   10291 
   10292   if (!right_type->IsInhabited()) {
   10293     Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation",
   10294                      Deoptimizer::SOFT);
   10295     right_type = Type::Any(zone());
   10296   } else {
   10297     if (!maybe_string_add) right = TruncateToNumber(right, &right_type);
   10298     right_rep = Representation::FromType(right_type);
   10299   }
   10300 
   10301   // Special case for string addition here.
   10302   if (op == Token::ADD &&
   10303       (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
   10304     // Validate type feedback for left argument.
   10305     if (left_type->Is(Type::String())) {
   10306       left = BuildCheckString(left);
   10307     }
   10308 
   10309     // Validate type feedback for right argument.
   10310     if (right_type->Is(Type::String())) {
   10311       right = BuildCheckString(right);
   10312     }
   10313 
   10314     // Convert left argument as necessary.
   10315     if (left_type->Is(Type::Number())) {
   10316       DCHECK(right_type->Is(Type::String()));
   10317       left = BuildNumberToString(left, left_type);
   10318     } else if (!left_type->Is(Type::String())) {
   10319       DCHECK(right_type->Is(Type::String()));
   10320       HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_RIGHT);
   10321       Add<HPushArguments>(left, right);
   10322       return AddUncasted<HInvokeFunction>(function, 2);
   10323     }
   10324 
   10325     // Convert right argument as necessary.
   10326     if (right_type->Is(Type::Number())) {
   10327       DCHECK(left_type->Is(Type::String()));
   10328       right = BuildNumberToString(right, right_type);
   10329     } else if (!right_type->Is(Type::String())) {
   10330       DCHECK(left_type->Is(Type::String()));
   10331       HValue* function = AddLoadJSBuiltin(Builtins::STRING_ADD_LEFT);
   10332       Add<HPushArguments>(left, right);
   10333       return AddUncasted<HInvokeFunction>(function, 2);
   10334     }
   10335 
   10336     // Fast path for empty constant strings.
   10337     if (left->IsConstant() &&
   10338         HConstant::cast(left)->HasStringValue() &&
   10339         HConstant::cast(left)->StringValue()->length() == 0) {
   10340       return right;
   10341     }
   10342     if (right->IsConstant() &&
   10343         HConstant::cast(right)->HasStringValue() &&
   10344         HConstant::cast(right)->StringValue()->length() == 0) {
   10345       return left;
   10346     }
   10347 
   10348     // Register the dependent code with the allocation site.
   10349     if (!allocation_mode.feedback_site().is_null()) {
   10350       DCHECK(!graph()->info()->IsStub());
   10351       Handle<AllocationSite> site(allocation_mode.feedback_site());
   10352       AllocationSite::AddDependentCompilationInfo(
   10353           site, AllocationSite::TENURING, top_info());
   10354     }
   10355 
   10356     // Inline the string addition into the stub when creating allocation
   10357     // mementos to gather allocation site feedback, or if we can statically
   10358     // infer that we're going to create a cons string.
   10359     if ((graph()->info()->IsStub() &&
   10360          allocation_mode.CreateAllocationMementos()) ||
   10361         (left->IsConstant() &&
   10362          HConstant::cast(left)->HasStringValue() &&
   10363          HConstant::cast(left)->StringValue()->length() + 1 >=
   10364            ConsString::kMinLength) ||
   10365         (right->IsConstant() &&
   10366          HConstant::cast(right)->HasStringValue() &&
   10367          HConstant::cast(right)->StringValue()->length() + 1 >=
   10368            ConsString::kMinLength)) {
   10369       return BuildStringAdd(left, right, allocation_mode);
   10370     }
   10371 
   10372     // Fallback to using the string add stub.
   10373     return AddUncasted<HStringAdd>(
   10374         left, right, allocation_mode.GetPretenureMode(),
   10375         STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
   10376   }
   10377 
   10378   if (graph()->info()->IsStub()) {
   10379     left = EnforceNumberType(left, left_type);
   10380     right = EnforceNumberType(right, right_type);
   10381   }
   10382 
   10383   Representation result_rep = Representation::FromType(result_type);
   10384 
   10385   bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
   10386                           (right_rep.IsTagged() && !right_rep.IsSmi());
   10387 
   10388   HInstruction* instr = NULL;
   10389   // Only the stub is allowed to call into the runtime, since otherwise we would
   10390   // inline several instructions (including the two pushes) for every tagged
   10391   // operation in optimized code, which is more expensive, than a stub call.
   10392   if (graph()->info()->IsStub() && is_non_primitive) {
   10393     HValue* function = AddLoadJSBuiltin(BinaryOpIC::TokenToJSBuiltin(op));
   10394     Add<HPushArguments>(left, right);
   10395     instr = AddUncasted<HInvokeFunction>(function, 2);
   10396   } else {
   10397     switch (op) {
   10398       case Token::ADD:
   10399         instr = AddUncasted<HAdd>(left, right);
   10400         break;
   10401       case Token::SUB:
   10402         instr = AddUncasted<HSub>(left, right);
   10403         break;
   10404       case Token::MUL:
   10405         instr = AddUncasted<HMul>(left, right);
   10406         break;
   10407       case Token::MOD: {
   10408         if (fixed_right_arg.has_value &&
   10409             !right->EqualsInteger32Constant(fixed_right_arg.value)) {
   10410           HConstant* fixed_right = Add<HConstant>(
   10411               static_cast<int>(fixed_right_arg.value));
   10412           IfBuilder if_same(this);
   10413           if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
   10414           if_same.Then();
   10415           if_same.ElseDeopt("Unexpected RHS of binary operation");
   10416           right = fixed_right;
   10417         }
   10418         instr = AddUncasted<HMod>(left, right);
   10419         break;
   10420       }
   10421       case Token::DIV:
   10422         instr = AddUncasted<HDiv>(left, right);
   10423         break;
   10424       case Token::BIT_XOR:
   10425       case Token::BIT_AND:
   10426         instr = AddUncasted<HBitwise>(op, left, right);
   10427         break;
   10428       case Token::BIT_OR: {
   10429         HValue* operand, *shift_amount;
   10430         if (left_type->Is(Type::Signed32()) &&
   10431             right_type->Is(Type::Signed32()) &&
   10432             MatchRotateRight(left, right, &operand, &shift_amount)) {
   10433           instr = AddUncasted<HRor>(operand, shift_amount);
   10434         } else {
   10435           instr = AddUncasted<HBitwise>(op, left, right);
   10436         }
   10437         break;
   10438       }
   10439       case Token::SAR:
   10440         instr = AddUncasted<HSar>(left, right);
   10441         break;
   10442       case Token::SHR:
   10443         instr = AddUncasted<HShr>(left, right);
   10444         if (FLAG_opt_safe_uint32_operations && instr->IsShr() &&
   10445             CanBeZero(right)) {
   10446           graph()->RecordUint32Instruction(instr);
   10447         }
   10448         break;
   10449       case Token::SHL:
   10450         instr = AddUncasted<HShl>(left, right);
   10451         break;
   10452       default:
   10453         UNREACHABLE();
   10454     }
   10455   }
   10456 
   10457   if (instr->IsBinaryOperation()) {
   10458     HBinaryOperation* binop = HBinaryOperation::cast(instr);
   10459     binop->set_observed_input_representation(1, left_rep);
   10460     binop->set_observed_input_representation(2, right_rep);
   10461     binop->initialize_output_representation(result_rep);
   10462     if (graph()->info()->IsStub()) {
   10463       // Stub should not call into stub.
   10464       instr->SetFlag(HValue::kCannotBeTagged);
   10465       // And should truncate on HForceRepresentation already.
   10466       if (left->IsForceRepresentation()) {
   10467         left->CopyFlag(HValue::kTruncatingToSmi, instr);
   10468         left->CopyFlag(HValue::kTruncatingToInt32, instr);
   10469       }
   10470       if (right->IsForceRepresentation()) {
   10471         right->CopyFlag(HValue::kTruncatingToSmi, instr);
   10472         right->CopyFlag(HValue::kTruncatingToInt32, instr);
   10473       }
   10474     }
   10475   }
   10476   return instr;
   10477 }
   10478 
   10479 
   10480 // Check for the form (%_ClassOf(foo) === 'BarClass').
   10481 static bool IsClassOfTest(CompareOperation* expr) {
   10482   if (expr->op() != Token::EQ_STRICT) return false;
   10483   CallRuntime* call = expr->left()->AsCallRuntime();
   10484   if (call == NULL) return false;
   10485   Literal* literal = expr->right()->AsLiteral();
   10486   if (literal == NULL) return false;
   10487   if (!literal->value()->IsString()) return false;
   10488   if (!call->name()->IsOneByteEqualTo(STATIC_CHAR_VECTOR("_ClassOf"))) {
   10489     return false;
   10490   }
   10491   DCHECK(call->arguments()->length() == 1);
   10492   return true;
   10493 }
   10494 
   10495 
   10496 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
   10497   DCHECK(!HasStackOverflow());
   10498   DCHECK(current_block() != NULL);
   10499   DCHECK(current_block()->HasPredecessor());
   10500   switch (expr->op()) {
   10501     case Token::COMMA:
   10502       return VisitComma(expr);
   10503     case Token::OR:
   10504     case Token::AND:
   10505       return VisitLogicalExpression(expr);
   10506     default:
   10507       return VisitArithmeticExpression(expr);
   10508   }
   10509 }
   10510 
   10511 
   10512 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) {
   10513   CHECK_ALIVE(VisitForEffect(expr->left()));
   10514   // Visit the right subexpression in the same AST context as the entire
   10515   // expression.
   10516   Visit(expr->right());
   10517 }
   10518 
   10519 
   10520 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
   10521   bool is_logical_and = expr->op() == Token::AND;
   10522   if (ast_context()->IsTest()) {
   10523     TestContext* context = TestContext::cast(ast_context());
   10524     // Translate left subexpression.
   10525     HBasicBlock* eval_right = graph()->CreateBasicBlock();
   10526     if (is_logical_and) {
   10527       CHECK_BAILOUT(VisitForControl(expr->left(),
   10528                                     eval_right,
   10529                                     context->if_false()));
   10530     } else {
   10531       CHECK_BAILOUT(VisitForControl(expr->left(),
   10532                                     context->if_true(),
   10533                                     eval_right));
   10534     }
   10535 
   10536     // Translate right subexpression by visiting it in the same AST
   10537     // context as the entire expression.
   10538     if (eval_right->HasPredecessor()) {
   10539       eval_right->SetJoinId(expr->RightId());
   10540       set_current_block(eval_right);
   10541       Visit(expr->right());
   10542     }
   10543 
   10544   } else if (ast_context()->IsValue()) {
   10545     CHECK_ALIVE(VisitForValue(expr->left()));
   10546     DCHECK(current_block() != NULL);
   10547     HValue* left_value = Top();
   10548 
   10549     // Short-circuit left values that always evaluate to the same boolean value.
   10550     if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
   10551       // l (evals true)  && r -> r
   10552       // l (evals true)  || r -> l
   10553       // l (evals false) && r -> l
   10554       // l (evals false) || r -> r
   10555       if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
   10556         Drop(1);
   10557         CHECK_ALIVE(VisitForValue(expr->right()));
   10558       }
   10559       return ast_context()->ReturnValue(Pop());
   10560     }
   10561 
   10562     // We need an extra block to maintain edge-split form.
   10563     HBasicBlock* empty_block = graph()->CreateBasicBlock();
   10564     HBasicBlock* eval_right = graph()->CreateBasicBlock();
   10565     ToBooleanStub::Types expected(expr->left()->to_boolean_types());
   10566     HBranch* test = is_logical_and
   10567         ? New<HBranch>(left_value, expected, eval_right, empty_block)
   10568         : New<HBranch>(left_value, expected, empty_block, eval_right);
   10569     FinishCurrentBlock(test);
   10570 
   10571     set_current_block(eval_right);
   10572     Drop(1);  // Value of the left subexpression.
   10573     CHECK_BAILOUT(VisitForValue(expr->right()));
   10574 
   10575     HBasicBlock* join_block =
   10576       CreateJoin(empty_block, current_block(), expr->id());
   10577     set_current_block(join_block);
   10578     return ast_context()->ReturnValue(Pop());
   10579 
   10580   } else {
   10581     DCHECK(ast_context()->IsEffect());
   10582     // In an effect context, we don't need the value of the left subexpression,
   10583     // only its control flow and side effects.  We need an extra block to
   10584     // maintain edge-split form.
   10585     HBasicBlock* empty_block = graph()->CreateBasicBlock();
   10586     HBasicBlock* right_block = graph()->CreateBasicBlock();
   10587     if (is_logical_and) {
   10588       CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
   10589     } else {
   10590       CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
   10591     }
   10592 
   10593     // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
   10594     // actually two empty blocks (one here and one inserted by
   10595     // TestContext::BuildBranch, and that they both have an HSimulate though the
   10596     // second one is not a merge node, and that we really have no good AST ID to
   10597     // put on that first HSimulate.
   10598 
   10599     if (empty_block->HasPredecessor()) {
   10600       empty_block->SetJoinId(expr->id());
   10601     } else {
   10602       empty_block = NULL;
   10603     }
   10604 
   10605     if (right_block->HasPredecessor()) {
   10606       right_block->SetJoinId(expr->RightId());
   10607       set_current_block(right_block);
   10608       CHECK_BAILOUT(VisitForEffect(expr->right()));
   10609       right_block = current_block();
   10610     } else {
   10611       right_block = NULL;
   10612     }
   10613 
   10614     HBasicBlock* join_block =
   10615       CreateJoin(empty_block, right_block, expr->id());
   10616     set_current_block(join_block);
   10617     // We did not materialize any value in the predecessor environments,
   10618     // so there is no need to handle it here.
   10619   }
   10620 }
   10621 
   10622 
   10623 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
   10624   CHECK_ALIVE(VisitForValue(expr->left()));
   10625   CHECK_ALIVE(VisitForValue(expr->right()));
   10626   SetSourcePosition(expr->position());
   10627   HValue* right = Pop();
   10628   HValue* left = Pop();
   10629   HValue* result =
   10630       BuildBinaryOperation(expr, left, right,
   10631           ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
   10632                                     : PUSH_BEFORE_SIMULATE);
   10633   if (FLAG_hydrogen_track_positions && result->IsBinaryOperation()) {
   10634     HBinaryOperation::cast(result)->SetOperandPositions(
   10635         zone(),
   10636         ScriptPositionToSourcePosition(expr->left()->position()),
   10637         ScriptPositionToSourcePosition(expr->right()->position()));
   10638   }
   10639   return ast_context()->ReturnValue(result);
   10640 }
   10641 
   10642 
   10643 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
   10644                                                         Expression* sub_expr,
   10645                                                         Handle<String> check) {
   10646   CHECK_ALIVE(VisitForTypeOf(sub_expr));
   10647   SetSourcePosition(expr->position());
   10648   HValue* value = Pop();
   10649   HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
   10650   return ast_context()->ReturnControl(instr, expr->id());
   10651 }
   10652 
   10653 
   10654 static bool IsLiteralCompareBool(Isolate* isolate,
   10655                                  HValue* left,
   10656                                  Token::Value op,
   10657                                  HValue* right) {
   10658   return op == Token::EQ_STRICT &&
   10659       ((left->IsConstant() &&
   10660           HConstant::cast(left)->handle(isolate)->IsBoolean()) ||
   10661        (right->IsConstant() &&
   10662            HConstant::cast(right)->handle(isolate)->IsBoolean()));
   10663 }
   10664 
   10665 
   10666 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
   10667   DCHECK(!HasStackOverflow());
   10668   DCHECK(current_block() != NULL);
   10669   DCHECK(current_block()->HasPredecessor());
   10670 
   10671   if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
   10672 
   10673   // Check for a few fast cases. The AST visiting behavior must be in sync
   10674   // with the full codegen: We don't push both left and right values onto
   10675   // the expression stack when one side is a special-case literal.
   10676   Expression* sub_expr = NULL;
   10677   Handle<String> check;
   10678   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
   10679     return HandleLiteralCompareTypeof(expr, sub_expr, check);
   10680   }
   10681   if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
   10682     return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
   10683   }
   10684   if (expr->IsLiteralCompareNull(&sub_expr)) {
   10685     return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
   10686   }
   10687 
   10688   if (IsClassOfTest(expr)) {
   10689     CallRuntime* call = expr->left()->AsCallRuntime();
   10690     DCHECK(call->arguments()->length() == 1);
   10691     CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   10692     HValue* value = Pop();
   10693     Literal* literal = expr->right()->AsLiteral();
   10694     Handle<String> rhs = Handle<String>::cast(literal->value());
   10695     HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
   10696     return ast_context()->ReturnControl(instr, expr->id());
   10697   }
   10698 
   10699   Type* left_type = expr->left()->bounds().lower;
   10700   Type* right_type = expr->right()->bounds().lower;
   10701   Type* combined_type = expr->combined_type();
   10702 
   10703   CHECK_ALIVE(VisitForValue(expr->left()));
   10704   CHECK_ALIVE(VisitForValue(expr->right()));
   10705 
   10706   if (FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
   10707 
   10708   HValue* right = Pop();
   10709   HValue* left = Pop();
   10710   Token::Value op = expr->op();
   10711 
   10712   if (IsLiteralCompareBool(isolate(), left, op, right)) {
   10713     HCompareObjectEqAndBranch* result =
   10714         New<HCompareObjectEqAndBranch>(left, right);
   10715     return ast_context()->ReturnControl(result, expr->id());
   10716   }
   10717 
   10718   if (op == Token::INSTANCEOF) {
   10719     // Check to see if the rhs of the instanceof is a global function not
   10720     // residing in new space. If it is we assume that the function will stay the
   10721     // same.
   10722     Handle<JSFunction> target = Handle<JSFunction>::null();
   10723     VariableProxy* proxy = expr->right()->AsVariableProxy();
   10724     bool global_function = (proxy != NULL) && proxy->var()->IsUnallocated();
   10725     if (global_function && current_info()->has_global_object()) {
   10726       Handle<String> name = proxy->name();
   10727       Handle<GlobalObject> global(current_info()->global_object());
   10728       LookupIterator it(global, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
   10729       Handle<Object> value = JSObject::GetDataProperty(&it);
   10730       if (it.IsFound() && value->IsJSFunction()) {
   10731         Handle<JSFunction> candidate = Handle<JSFunction>::cast(value);
   10732         // If the function is in new space we assume it's more likely to
   10733         // change and thus prefer the general IC code.
   10734         if (!isolate()->heap()->InNewSpace(*candidate)) {
   10735           target = candidate;
   10736         }
   10737       }
   10738     }
   10739 
   10740     // If the target is not null we have found a known global function that is
   10741     // assumed to stay the same for this instanceof.
   10742     if (target.is_null()) {
   10743       HInstanceOf* result = New<HInstanceOf>(left, right);
   10744       return ast_context()->ReturnInstruction(result, expr->id());
   10745     } else {
   10746       Add<HCheckValue>(right, target);
   10747       HInstanceOfKnownGlobal* result =
   10748         New<HInstanceOfKnownGlobal>(left, target);
   10749       return ast_context()->ReturnInstruction(result, expr->id());
   10750     }
   10751 
   10752     // Code below assumes that we don't fall through.
   10753     UNREACHABLE();
   10754   } else if (op == Token::IN) {
   10755     HValue* function = AddLoadJSBuiltin(Builtins::IN);
   10756     Add<HPushArguments>(left, right);
   10757     // TODO(olivf) InvokeFunction produces a check for the parameter count,
   10758     // even though we are certain to pass the correct number of arguments here.
   10759     HInstruction* result = New<HInvokeFunction>(function, 2);
   10760     return ast_context()->ReturnInstruction(result, expr->id());
   10761   }
   10762 
   10763   PushBeforeSimulateBehavior push_behavior =
   10764     ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
   10765                               : PUSH_BEFORE_SIMULATE;
   10766   HControlInstruction* compare = BuildCompareInstruction(
   10767       op, left, right, left_type, right_type, combined_type,
   10768       ScriptPositionToSourcePosition(expr->left()->position()),
   10769       ScriptPositionToSourcePosition(expr->right()->position()),
   10770       push_behavior, expr->id());
   10771   if (compare == NULL) return;  // Bailed out.
   10772   return ast_context()->ReturnControl(compare, expr->id());
   10773 }
   10774 
   10775 
   10776 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
   10777     Token::Value op,
   10778     HValue* left,
   10779     HValue* right,
   10780     Type* left_type,
   10781     Type* right_type,
   10782     Type* combined_type,
   10783     HSourcePosition left_position,
   10784     HSourcePosition right_position,
   10785     PushBeforeSimulateBehavior push_sim_result,
   10786     BailoutId bailout_id) {
   10787   // Cases handled below depend on collected type feedback. They should
   10788   // soft deoptimize when there is no type feedback.
   10789   if (!combined_type->IsInhabited()) {
   10790     Add<HDeoptimize>("Insufficient type feedback for combined type "
   10791                      "of binary operation",
   10792                      Deoptimizer::SOFT);
   10793     combined_type = left_type = right_type = Type::Any(zone());
   10794   }
   10795 
   10796   Representation left_rep = Representation::FromType(left_type);
   10797   Representation right_rep = Representation::FromType(right_type);
   10798   Representation combined_rep = Representation::FromType(combined_type);
   10799 
   10800   if (combined_type->Is(Type::Receiver())) {
   10801     if (Token::IsEqualityOp(op)) {
   10802       // HCompareObjectEqAndBranch can only deal with object, so
   10803       // exclude numbers.
   10804       if ((left->IsConstant() &&
   10805            HConstant::cast(left)->HasNumberValue()) ||
   10806           (right->IsConstant() &&
   10807            HConstant::cast(right)->HasNumberValue())) {
   10808         Add<HDeoptimize>("Type mismatch between feedback and constant",
   10809                          Deoptimizer::SOFT);
   10810         // The caller expects a branch instruction, so make it happy.
   10811         return New<HBranch>(graph()->GetConstantTrue());
   10812       }
   10813       // Can we get away with map check and not instance type check?
   10814       HValue* operand_to_check =
   10815           left->block()->block_id() < right->block()->block_id() ? left : right;
   10816       if (combined_type->IsClass()) {
   10817         Handle<Map> map = combined_type->AsClass()->Map();
   10818         AddCheckMap(operand_to_check, map);
   10819         HCompareObjectEqAndBranch* result =
   10820             New<HCompareObjectEqAndBranch>(left, right);
   10821         if (FLAG_hydrogen_track_positions) {
   10822           result->set_operand_position(zone(), 0, left_position);
   10823           result->set_operand_position(zone(), 1, right_position);
   10824         }
   10825         return result;
   10826       } else {
   10827         BuildCheckHeapObject(operand_to_check);
   10828         Add<HCheckInstanceType>(operand_to_check,
   10829                                 HCheckInstanceType::IS_SPEC_OBJECT);
   10830         HCompareObjectEqAndBranch* result =
   10831             New<HCompareObjectEqAndBranch>(left, right);
   10832         return result;
   10833       }
   10834     } else {
   10835       Bailout(kUnsupportedNonPrimitiveCompare);
   10836       return NULL;
   10837     }
   10838   } else if (combined_type->Is(Type::InternalizedString()) &&
   10839              Token::IsEqualityOp(op)) {
   10840     // If we have a constant argument, it should be consistent with the type
   10841     // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
   10842     if ((left->IsConstant() &&
   10843          !HConstant::cast(left)->HasInternalizedStringValue()) ||
   10844         (right->IsConstant() &&
   10845          !HConstant::cast(right)->HasInternalizedStringValue())) {
   10846       Add<HDeoptimize>("Type mismatch between feedback and constant",
   10847                        Deoptimizer::SOFT);
   10848       // The caller expects a branch instruction, so make it happy.
   10849       return New<HBranch>(graph()->GetConstantTrue());
   10850     }
   10851     BuildCheckHeapObject(left);
   10852     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
   10853     BuildCheckHeapObject(right);
   10854     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
   10855     HCompareObjectEqAndBranch* result =
   10856         New<HCompareObjectEqAndBranch>(left, right);
   10857     return result;
   10858   } else if (combined_type->Is(Type::String())) {
   10859     BuildCheckHeapObject(left);
   10860     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
   10861     BuildCheckHeapObject(right);
   10862     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
   10863     HStringCompareAndBranch* result =
   10864         New<HStringCompareAndBranch>(left, right, op);
   10865     return result;
   10866   } else {
   10867     if (combined_rep.IsTagged() || combined_rep.IsNone()) {
   10868       HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
   10869       result->set_observed_input_representation(1, left_rep);
   10870       result->set_observed_input_representation(2, right_rep);
   10871       if (result->HasObservableSideEffects()) {
   10872         if (push_sim_result == PUSH_BEFORE_SIMULATE) {
   10873           Push(result);
   10874           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
   10875           Drop(1);
   10876         } else {
   10877           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
   10878         }
   10879       }
   10880       // TODO(jkummerow): Can we make this more efficient?
   10881       HBranch* branch = New<HBranch>(result);
   10882       return branch;
   10883     } else {
   10884       HCompareNumericAndBranch* result =
   10885           New<HCompareNumericAndBranch>(left, right, op);
   10886       result->set_observed_input_representation(left_rep, right_rep);
   10887       if (FLAG_hydrogen_track_positions) {
   10888         result->SetOperandPositions(zone(), left_position, right_position);
   10889       }
   10890       return result;
   10891     }
   10892   }
   10893 }
   10894 
   10895 
   10896 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
   10897                                                      Expression* sub_expr,
   10898                                                      NilValue nil) {
   10899   DCHECK(!HasStackOverflow());
   10900   DCHECK(current_block() != NULL);
   10901   DCHECK(current_block()->HasPredecessor());
   10902   DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
   10903   if (!FLAG_hydrogen_track_positions) SetSourcePosition(expr->position());
   10904   CHECK_ALIVE(VisitForValue(sub_expr));
   10905   HValue* value = Pop();
   10906   if (expr->op() == Token::EQ_STRICT) {
   10907     HConstant* nil_constant = nil == kNullValue
   10908         ? graph()->GetConstantNull()
   10909         : graph()->GetConstantUndefined();
   10910     HCompareObjectEqAndBranch* instr =
   10911         New<HCompareObjectEqAndBranch>(value, nil_constant);
   10912     return ast_context()->ReturnControl(instr, expr->id());
   10913   } else {
   10914     DCHECK_EQ(Token::EQ, expr->op());
   10915     Type* type = expr->combined_type()->Is(Type::None())
   10916         ? Type::Any(zone()) : expr->combined_type();
   10917     HIfContinuation continuation;
   10918     BuildCompareNil(value, type, &continuation);
   10919     return ast_context()->ReturnContinuation(&continuation, expr->id());
   10920   }
   10921 }
   10922 
   10923 
   10924 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
   10925   // If we share optimized code between different closures, the
   10926   // this-function is not a constant, except inside an inlined body.
   10927   if (function_state()->outer() != NULL) {
   10928       return New<HConstant>(
   10929           function_state()->compilation_info()->closure());
   10930   } else {
   10931       return New<HThisFunction>();
   10932   }
   10933 }
   10934 
   10935 
   10936 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
   10937     Handle<JSObject> boilerplate_object,
   10938     AllocationSiteUsageContext* site_context) {
   10939   NoObservableSideEffectsScope no_effects(this);
   10940   InstanceType instance_type = boilerplate_object->map()->instance_type();
   10941   DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
   10942 
   10943   HType type = instance_type == JS_ARRAY_TYPE
   10944       ? HType::JSArray() : HType::JSObject();
   10945   HValue* object_size_constant = Add<HConstant>(
   10946       boilerplate_object->map()->instance_size());
   10947 
   10948   PretenureFlag pretenure_flag = NOT_TENURED;
   10949   if (FLAG_allocation_site_pretenuring) {
   10950     pretenure_flag = site_context->current()->GetPretenureMode();
   10951     Handle<AllocationSite> site(site_context->current());
   10952     AllocationSite::AddDependentCompilationInfo(
   10953         site, AllocationSite::TENURING, top_info());
   10954   }
   10955 
   10956   HInstruction* object = Add<HAllocate>(object_size_constant, type,
   10957       pretenure_flag, instance_type, site_context->current());
   10958 
   10959   // If allocation folding reaches Page::kMaxRegularHeapObjectSize the
   10960   // elements array may not get folded into the object. Hence, we set the
   10961   // elements pointer to empty fixed array and let store elimination remove
   10962   // this store in the folding case.
   10963   HConstant* empty_fixed_array = Add<HConstant>(
   10964       isolate()->factory()->empty_fixed_array());
   10965   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   10966       empty_fixed_array);
   10967 
   10968   BuildEmitObjectHeader(boilerplate_object, object);
   10969 
   10970   Handle<FixedArrayBase> elements(boilerplate_object->elements());
   10971   int elements_size = (elements->length() > 0 &&
   10972       elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
   10973           elements->Size() : 0;
   10974 
   10975   if (pretenure_flag == TENURED &&
   10976       elements->map() == isolate()->heap()->fixed_cow_array_map() &&
   10977       isolate()->heap()->InNewSpace(*elements)) {
   10978     // If we would like to pretenure a fixed cow array, we must ensure that the
   10979     // array is already in old space, otherwise we'll create too many old-to-
   10980     // new-space pointers (overflowing the store buffer).
   10981     elements = Handle<FixedArrayBase>(
   10982         isolate()->factory()->CopyAndTenureFixedCOWArray(
   10983             Handle<FixedArray>::cast(elements)));
   10984     boilerplate_object->set_elements(*elements);
   10985   }
   10986 
   10987   HInstruction* object_elements = NULL;
   10988   if (elements_size > 0) {
   10989     HValue* object_elements_size = Add<HConstant>(elements_size);
   10990     InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
   10991         ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
   10992     object_elements = Add<HAllocate>(
   10993         object_elements_size, HType::HeapObject(),
   10994         pretenure_flag, instance_type, site_context->current());
   10995   }
   10996   BuildInitElementsInObjectHeader(boilerplate_object, object, object_elements);
   10997 
   10998   // Copy object elements if non-COW.
   10999   if (object_elements != NULL) {
   11000     BuildEmitElements(boilerplate_object, elements, object_elements,
   11001                       site_context);
   11002   }
   11003 
   11004   // Copy in-object properties.
   11005   if (boilerplate_object->map()->NumberOfFields() != 0 ||
   11006       boilerplate_object->map()->unused_property_fields() > 0) {
   11007     BuildEmitInObjectProperties(boilerplate_object, object, site_context,
   11008                                 pretenure_flag);
   11009   }
   11010   return object;
   11011 }
   11012 
   11013 
   11014 void HOptimizedGraphBuilder::BuildEmitObjectHeader(
   11015     Handle<JSObject> boilerplate_object,
   11016     HInstruction* object) {
   11017   DCHECK(boilerplate_object->properties()->length() == 0);
   11018 
   11019   Handle<Map> boilerplate_object_map(boilerplate_object->map());
   11020   AddStoreMapConstant(object, boilerplate_object_map);
   11021 
   11022   Handle<Object> properties_field =
   11023       Handle<Object>(boilerplate_object->properties(), isolate());
   11024   DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
   11025   HInstruction* properties = Add<HConstant>(properties_field);
   11026   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
   11027   Add<HStoreNamedField>(object, access, properties);
   11028 
   11029   if (boilerplate_object->IsJSArray()) {
   11030     Handle<JSArray> boilerplate_array =
   11031         Handle<JSArray>::cast(boilerplate_object);
   11032     Handle<Object> length_field =
   11033         Handle<Object>(boilerplate_array->length(), isolate());
   11034     HInstruction* length = Add<HConstant>(length_field);
   11035 
   11036     DCHECK(boilerplate_array->length()->IsSmi());
   11037     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
   11038         boilerplate_array->GetElementsKind()), length);
   11039   }
   11040 }
   11041 
   11042 
   11043 void HOptimizedGraphBuilder::BuildInitElementsInObjectHeader(
   11044     Handle<JSObject> boilerplate_object,
   11045     HInstruction* object,
   11046     HInstruction* object_elements) {
   11047   DCHECK(boilerplate_object->properties()->length() == 0);
   11048   if (object_elements == NULL) {
   11049     Handle<Object> elements_field =
   11050         Handle<Object>(boilerplate_object->elements(), isolate());
   11051     object_elements = Add<HConstant>(elements_field);
   11052   }
   11053   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11054       object_elements);
   11055 }
   11056 
   11057 
   11058 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
   11059     Handle<JSObject> boilerplate_object,
   11060     HInstruction* object,
   11061     AllocationSiteUsageContext* site_context,
   11062     PretenureFlag pretenure_flag) {
   11063   Handle<Map> boilerplate_map(boilerplate_object->map());
   11064   Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
   11065   int limit = boilerplate_map->NumberOfOwnDescriptors();
   11066 
   11067   int copied_fields = 0;
   11068   for (int i = 0; i < limit; i++) {
   11069     PropertyDetails details = descriptors->GetDetails(i);
   11070     if (details.type() != FIELD) continue;
   11071     copied_fields++;
   11072     int index = descriptors->GetFieldIndex(i);
   11073     int property_offset = boilerplate_object->GetInObjectPropertyOffset(index);
   11074     Handle<Name> name(descriptors->GetKey(i));
   11075     Handle<Object> value =
   11076         Handle<Object>(boilerplate_object->InObjectPropertyAt(index),
   11077         isolate());
   11078 
   11079     // The access for the store depends on the type of the boilerplate.
   11080     HObjectAccess access = boilerplate_object->IsJSArray() ?
   11081         HObjectAccess::ForJSArrayOffset(property_offset) :
   11082         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
   11083 
   11084     if (value->IsJSObject()) {
   11085       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   11086       Handle<AllocationSite> current_site = site_context->EnterNewScope();
   11087       HInstruction* result =
   11088           BuildFastLiteral(value_object, site_context);
   11089       site_context->ExitScope(current_site, value_object);
   11090       Add<HStoreNamedField>(object, access, result);
   11091     } else {
   11092       Representation representation = details.representation();
   11093       HInstruction* value_instruction;
   11094 
   11095       if (representation.IsDouble()) {
   11096         // Allocate a HeapNumber box and store the value into it.
   11097         HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
   11098         // This heap number alloc does not have a corresponding
   11099         // AllocationSite. That is okay because
   11100         // 1) it's a child object of another object with a valid allocation site
   11101         // 2) we can just use the mode of the parent object for pretenuring
   11102         HInstruction* double_box =
   11103             Add<HAllocate>(heap_number_constant, HType::HeapObject(),
   11104                 pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE);
   11105         AddStoreMapConstant(double_box,
   11106             isolate()->factory()->mutable_heap_number_map());
   11107         // Unwrap the mutable heap number from the boilerplate.
   11108         HValue* double_value =
   11109             Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
   11110         Add<HStoreNamedField>(
   11111             double_box, HObjectAccess::ForHeapNumberValue(), double_value);
   11112         value_instruction = double_box;
   11113       } else if (representation.IsSmi()) {
   11114         value_instruction = value->IsUninitialized()
   11115             ? graph()->GetConstant0()
   11116             : Add<HConstant>(value);
   11117         // Ensure that value is stored as smi.
   11118         access = access.WithRepresentation(representation);
   11119       } else {
   11120         value_instruction = Add<HConstant>(value);
   11121       }
   11122 
   11123       Add<HStoreNamedField>(object, access, value_instruction);
   11124     }
   11125   }
   11126 
   11127   int inobject_properties = boilerplate_object->map()->inobject_properties();
   11128   HInstruction* value_instruction =
   11129       Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
   11130   for (int i = copied_fields; i < inobject_properties; i++) {
   11131     DCHECK(boilerplate_object->IsJSObject());
   11132     int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
   11133     HObjectAccess access =
   11134         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
   11135     Add<HStoreNamedField>(object, access, value_instruction);
   11136   }
   11137 }
   11138 
   11139 
   11140 void HOptimizedGraphBuilder::BuildEmitElements(
   11141     Handle<JSObject> boilerplate_object,
   11142     Handle<FixedArrayBase> elements,
   11143     HValue* object_elements,
   11144     AllocationSiteUsageContext* site_context) {
   11145   ElementsKind kind = boilerplate_object->map()->elements_kind();
   11146   int elements_length = elements->length();
   11147   HValue* object_elements_length = Add<HConstant>(elements_length);
   11148   BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
   11149 
   11150   // Copy elements backing store content.
   11151   if (elements->IsFixedDoubleArray()) {
   11152     BuildEmitFixedDoubleArray(elements, kind, object_elements);
   11153   } else if (elements->IsFixedArray()) {
   11154     BuildEmitFixedArray(elements, kind, object_elements,
   11155                         site_context);
   11156   } else {
   11157     UNREACHABLE();
   11158   }
   11159 }
   11160 
   11161 
   11162 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
   11163     Handle<FixedArrayBase> elements,
   11164     ElementsKind kind,
   11165     HValue* object_elements) {
   11166   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   11167   int elements_length = elements->length();
   11168   for (int i = 0; i < elements_length; i++) {
   11169     HValue* key_constant = Add<HConstant>(i);
   11170     HInstruction* value_instruction =
   11171         Add<HLoadKeyed>(boilerplate_elements, key_constant,
   11172                         static_cast<HValue*>(NULL), kind,
   11173                         ALLOW_RETURN_HOLE);
   11174     HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
   11175                                            value_instruction, kind);
   11176     store->SetFlag(HValue::kAllowUndefinedAsNaN);
   11177   }
   11178 }
   11179 
   11180 
   11181 void HOptimizedGraphBuilder::BuildEmitFixedArray(
   11182     Handle<FixedArrayBase> elements,
   11183     ElementsKind kind,
   11184     HValue* object_elements,
   11185     AllocationSiteUsageContext* site_context) {
   11186   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   11187   int elements_length = elements->length();
   11188   Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
   11189   for (int i = 0; i < elements_length; i++) {
   11190     Handle<Object> value(fast_elements->get(i), isolate());
   11191     HValue* key_constant = Add<HConstant>(i);
   11192     if (value->IsJSObject()) {
   11193       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   11194       Handle<AllocationSite> current_site = site_context->EnterNewScope();
   11195       HInstruction* result =
   11196           BuildFastLiteral(value_object, site_context);
   11197       site_context->ExitScope(current_site, value_object);
   11198       Add<HStoreKeyed>(object_elements, key_constant, result, kind);
   11199     } else {
   11200       HInstruction* value_instruction =
   11201           Add<HLoadKeyed>(boilerplate_elements, key_constant,
   11202                           static_cast<HValue*>(NULL), kind,
   11203                           ALLOW_RETURN_HOLE);
   11204       Add<HStoreKeyed>(object_elements, key_constant, value_instruction, kind);
   11205     }
   11206   }
   11207 }
   11208 
   11209 
   11210 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
   11211   DCHECK(!HasStackOverflow());
   11212   DCHECK(current_block() != NULL);
   11213   DCHECK(current_block()->HasPredecessor());
   11214   HInstruction* instr = BuildThisFunction();
   11215   return ast_context()->ReturnInstruction(instr, expr->id());
   11216 }
   11217 
   11218 
   11219 void HOptimizedGraphBuilder::VisitSuperReference(SuperReference* expr) {
   11220   DCHECK(!HasStackOverflow());
   11221   DCHECK(current_block() != NULL);
   11222   DCHECK(current_block()->HasPredecessor());
   11223   return Bailout(kSuperReference);
   11224 }
   11225 
   11226 
   11227 void HOptimizedGraphBuilder::VisitDeclarations(
   11228     ZoneList<Declaration*>* declarations) {
   11229   DCHECK(globals_.is_empty());
   11230   AstVisitor::VisitDeclarations(declarations);
   11231   if (!globals_.is_empty()) {
   11232     Handle<FixedArray> array =
   11233        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
   11234     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
   11235     int flags = DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
   11236         DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
   11237         DeclareGlobalsStrictMode::encode(current_info()->strict_mode());
   11238     Add<HDeclareGlobals>(array, flags);
   11239     globals_.Rewind(0);
   11240   }
   11241 }
   11242 
   11243 
   11244 void HOptimizedGraphBuilder::VisitVariableDeclaration(
   11245     VariableDeclaration* declaration) {
   11246   VariableProxy* proxy = declaration->proxy();
   11247   VariableMode mode = declaration->mode();
   11248   Variable* variable = proxy->var();
   11249   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
   11250   switch (variable->location()) {
   11251     case Variable::UNALLOCATED:
   11252       globals_.Add(variable->name(), zone());
   11253       globals_.Add(variable->binding_needs_init()
   11254                        ? isolate()->factory()->the_hole_value()
   11255                        : isolate()->factory()->undefined_value(), zone());
   11256       return;
   11257     case Variable::PARAMETER:
   11258     case Variable::LOCAL:
   11259       if (hole_init) {
   11260         HValue* value = graph()->GetConstantHole();
   11261         environment()->Bind(variable, value);
   11262       }
   11263       break;
   11264     case Variable::CONTEXT:
   11265       if (hole_init) {
   11266         HValue* value = graph()->GetConstantHole();
   11267         HValue* context = environment()->context();
   11268         HStoreContextSlot* store = Add<HStoreContextSlot>(
   11269             context, variable->index(), HStoreContextSlot::kNoCheck, value);
   11270         if (store->HasObservableSideEffects()) {
   11271           Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
   11272         }
   11273       }
   11274       break;
   11275     case Variable::LOOKUP:
   11276       return Bailout(kUnsupportedLookupSlotInDeclaration);
   11277   }
   11278 }
   11279 
   11280 
   11281 void HOptimizedGraphBuilder::VisitFunctionDeclaration(
   11282     FunctionDeclaration* declaration) {
   11283   VariableProxy* proxy = declaration->proxy();
   11284   Variable* variable = proxy->var();
   11285   switch (variable->location()) {
   11286     case Variable::UNALLOCATED: {
   11287       globals_.Add(variable->name(), zone());
   11288       Handle<SharedFunctionInfo> function = Compiler::BuildFunctionInfo(
   11289           declaration->fun(), current_info()->script(), top_info());
   11290       // Check for stack-overflow exception.
   11291       if (function.is_null()) return SetStackOverflow();
   11292       globals_.Add(function, zone());
   11293       return;
   11294     }
   11295     case Variable::PARAMETER:
   11296     case Variable::LOCAL: {
   11297       CHECK_ALIVE(VisitForValue(declaration->fun()));
   11298       HValue* value = Pop();
   11299       BindIfLive(variable, value);
   11300       break;
   11301     }
   11302     case Variable::CONTEXT: {
   11303       CHECK_ALIVE(VisitForValue(declaration->fun()));
   11304       HValue* value = Pop();
   11305       HValue* context = environment()->context();
   11306       HStoreContextSlot* store = Add<HStoreContextSlot>(
   11307           context, variable->index(), HStoreContextSlot::kNoCheck, value);
   11308       if (store->HasObservableSideEffects()) {
   11309         Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
   11310       }
   11311       break;
   11312     }
   11313     case Variable::LOOKUP:
   11314       return Bailout(kUnsupportedLookupSlotInDeclaration);
   11315   }
   11316 }
   11317 
   11318 
   11319 void HOptimizedGraphBuilder::VisitModuleDeclaration(
   11320     ModuleDeclaration* declaration) {
   11321   UNREACHABLE();
   11322 }
   11323 
   11324 
   11325 void HOptimizedGraphBuilder::VisitImportDeclaration(
   11326     ImportDeclaration* declaration) {
   11327   UNREACHABLE();
   11328 }
   11329 
   11330 
   11331 void HOptimizedGraphBuilder::VisitExportDeclaration(
   11332     ExportDeclaration* declaration) {
   11333   UNREACHABLE();
   11334 }
   11335 
   11336 
   11337 void HOptimizedGraphBuilder::VisitModuleLiteral(ModuleLiteral* module) {
   11338   UNREACHABLE();
   11339 }
   11340 
   11341 
   11342 void HOptimizedGraphBuilder::VisitModuleVariable(ModuleVariable* module) {
   11343   UNREACHABLE();
   11344 }
   11345 
   11346 
   11347 void HOptimizedGraphBuilder::VisitModulePath(ModulePath* module) {
   11348   UNREACHABLE();
   11349 }
   11350 
   11351 
   11352 void HOptimizedGraphBuilder::VisitModuleUrl(ModuleUrl* module) {
   11353   UNREACHABLE();
   11354 }
   11355 
   11356 
   11357 void HOptimizedGraphBuilder::VisitModuleStatement(ModuleStatement* stmt) {
   11358   UNREACHABLE();
   11359 }
   11360 
   11361 
   11362 // Generators for inline runtime functions.
   11363 // Support for types.
   11364 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
   11365   DCHECK(call->arguments()->length() == 1);
   11366   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11367   HValue* value = Pop();
   11368   HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
   11369   return ast_context()->ReturnControl(result, call->id());
   11370 }
   11371 
   11372 
   11373 void HOptimizedGraphBuilder::GenerateIsSpecObject(CallRuntime* call) {
   11374   DCHECK(call->arguments()->length() == 1);
   11375   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11376   HValue* value = Pop();
   11377   HHasInstanceTypeAndBranch* result =
   11378       New<HHasInstanceTypeAndBranch>(value,
   11379                                      FIRST_SPEC_OBJECT_TYPE,
   11380                                      LAST_SPEC_OBJECT_TYPE);
   11381   return ast_context()->ReturnControl(result, call->id());
   11382 }
   11383 
   11384 
   11385 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
   11386   DCHECK(call->arguments()->length() == 1);
   11387   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11388   HValue* value = Pop();
   11389   HHasInstanceTypeAndBranch* result =
   11390       New<HHasInstanceTypeAndBranch>(value, JS_FUNCTION_TYPE);
   11391   return ast_context()->ReturnControl(result, call->id());
   11392 }
   11393 
   11394 
   11395 void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) {
   11396   DCHECK(call->arguments()->length() == 1);
   11397   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11398   HValue* value = Pop();
   11399   HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value);
   11400   return ast_context()->ReturnControl(result, call->id());
   11401 }
   11402 
   11403 
   11404 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
   11405   DCHECK(call->arguments()->length() == 1);
   11406   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11407   HValue* value = Pop();
   11408   HHasCachedArrayIndexAndBranch* result =
   11409       New<HHasCachedArrayIndexAndBranch>(value);
   11410   return ast_context()->ReturnControl(result, call->id());
   11411 }
   11412 
   11413 
   11414 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
   11415   DCHECK(call->arguments()->length() == 1);
   11416   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11417   HValue* value = Pop();
   11418   HHasInstanceTypeAndBranch* result =
   11419       New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
   11420   return ast_context()->ReturnControl(result, call->id());
   11421 }
   11422 
   11423 
   11424 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
   11425   DCHECK(call->arguments()->length() == 1);
   11426   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11427   HValue* value = Pop();
   11428   HHasInstanceTypeAndBranch* result =
   11429       New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE);
   11430   return ast_context()->ReturnControl(result, call->id());
   11431 }
   11432 
   11433 
   11434 void HOptimizedGraphBuilder::GenerateIsObject(CallRuntime* call) {
   11435   DCHECK(call->arguments()->length() == 1);
   11436   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11437   HValue* value = Pop();
   11438   HIsObjectAndBranch* result = New<HIsObjectAndBranch>(value);
   11439   return ast_context()->ReturnControl(result, call->id());
   11440 }
   11441 
   11442 
   11443 void HOptimizedGraphBuilder::GenerateIsNonNegativeSmi(CallRuntime* call) {
   11444   return Bailout(kInlinedRuntimeFunctionIsNonNegativeSmi);
   11445 }
   11446 
   11447 
   11448 void HOptimizedGraphBuilder::GenerateIsUndetectableObject(CallRuntime* call) {
   11449   DCHECK(call->arguments()->length() == 1);
   11450   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11451   HValue* value = Pop();
   11452   HIsUndetectableAndBranch* result = New<HIsUndetectableAndBranch>(value);
   11453   return ast_context()->ReturnControl(result, call->id());
   11454 }
   11455 
   11456 
   11457 void HOptimizedGraphBuilder::GenerateIsStringWrapperSafeForDefaultValueOf(
   11458     CallRuntime* call) {
   11459   return Bailout(kInlinedRuntimeFunctionIsStringWrapperSafeForDefaultValueOf);
   11460 }
   11461 
   11462 
   11463 // Support for construct call checks.
   11464 void HOptimizedGraphBuilder::GenerateIsConstructCall(CallRuntime* call) {
   11465   DCHECK(call->arguments()->length() == 0);
   11466   if (function_state()->outer() != NULL) {
   11467     // We are generating graph for inlined function.
   11468     HValue* value = function_state()->inlining_kind() == CONSTRUCT_CALL_RETURN
   11469         ? graph()->GetConstantTrue()
   11470         : graph()->GetConstantFalse();
   11471     return ast_context()->ReturnValue(value);
   11472   } else {
   11473     return ast_context()->ReturnControl(New<HIsConstructCallAndBranch>(),
   11474                                         call->id());
   11475   }
   11476 }
   11477 
   11478 
   11479 // Support for arguments.length and arguments[?].
   11480 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
   11481   DCHECK(call->arguments()->length() == 0);
   11482   HInstruction* result = NULL;
   11483   if (function_state()->outer() == NULL) {
   11484     HInstruction* elements = Add<HArgumentsElements>(false);
   11485     result = New<HArgumentsLength>(elements);
   11486   } else {
   11487     // Number of arguments without receiver.
   11488     int argument_count = environment()->
   11489         arguments_environment()->parameter_count() - 1;
   11490     result = New<HConstant>(argument_count);
   11491   }
   11492   return ast_context()->ReturnInstruction(result, call->id());
   11493 }
   11494 
   11495 
   11496 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
   11497   DCHECK(call->arguments()->length() == 1);
   11498   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11499   HValue* index = Pop();
   11500   HInstruction* result = NULL;
   11501   if (function_state()->outer() == NULL) {
   11502     HInstruction* elements = Add<HArgumentsElements>(false);
   11503     HInstruction* length = Add<HArgumentsLength>(elements);
   11504     HInstruction* checked_index = Add<HBoundsCheck>(index, length);
   11505     result = New<HAccessArgumentsAt>(elements, length, checked_index);
   11506   } else {
   11507     EnsureArgumentsArePushedForAccess();
   11508 
   11509     // Number of arguments without receiver.
   11510     HInstruction* elements = function_state()->arguments_elements();
   11511     int argument_count = environment()->
   11512         arguments_environment()->parameter_count() - 1;
   11513     HInstruction* length = Add<HConstant>(argument_count);
   11514     HInstruction* checked_key = Add<HBoundsCheck>(index, length);
   11515     result = New<HAccessArgumentsAt>(elements, length, checked_key);
   11516   }
   11517   return ast_context()->ReturnInstruction(result, call->id());
   11518 }
   11519 
   11520 
   11521 // Support for accessing the class and value fields of an object.
   11522 void HOptimizedGraphBuilder::GenerateClassOf(CallRuntime* call) {
   11523   // The special form detected by IsClassOfTest is detected before we get here
   11524   // and does not cause a bailout.
   11525   return Bailout(kInlinedRuntimeFunctionClassOf);
   11526 }
   11527 
   11528 
   11529 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
   11530   DCHECK(call->arguments()->length() == 1);
   11531   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11532   HValue* object = Pop();
   11533 
   11534   IfBuilder if_objectisvalue(this);
   11535   HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>(
   11536       object, JS_VALUE_TYPE);
   11537   if_objectisvalue.Then();
   11538   {
   11539     // Return the actual value.
   11540     Push(Add<HLoadNamedField>(
   11541             object, objectisvalue,
   11542             HObjectAccess::ForObservableJSObjectOffset(
   11543                 JSValue::kValueOffset)));
   11544     Add<HSimulate>(call->id(), FIXED_SIMULATE);
   11545   }
   11546   if_objectisvalue.Else();
   11547   {
   11548     // If the object is not a value return the object.
   11549     Push(object);
   11550     Add<HSimulate>(call->id(), FIXED_SIMULATE);
   11551   }
   11552   if_objectisvalue.End();
   11553   return ast_context()->ReturnValue(Pop());
   11554 }
   11555 
   11556 
   11557 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
   11558   DCHECK(call->arguments()->length() == 2);
   11559   DCHECK_NE(NULL, call->arguments()->at(1)->AsLiteral());
   11560   Smi* index = Smi::cast(*(call->arguments()->at(1)->AsLiteral()->value()));
   11561   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11562   HValue* date = Pop();
   11563   HDateField* result = New<HDateField>(date, index);
   11564   return ast_context()->ReturnInstruction(result, call->id());
   11565 }
   11566 
   11567 
   11568 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
   11569     CallRuntime* call) {
   11570   DCHECK(call->arguments()->length() == 3);
   11571   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11572   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11573   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
   11574   HValue* string = Pop();
   11575   HValue* value = Pop();
   11576   HValue* index = Pop();
   11577   Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
   11578                          index, value);
   11579   Add<HSimulate>(call->id(), FIXED_SIMULATE);
   11580   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   11581 }
   11582 
   11583 
   11584 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
   11585     CallRuntime* call) {
   11586   DCHECK(call->arguments()->length() == 3);
   11587   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11588   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11589   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
   11590   HValue* string = Pop();
   11591   HValue* value = Pop();
   11592   HValue* index = Pop();
   11593   Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
   11594                          index, value);
   11595   Add<HSimulate>(call->id(), FIXED_SIMULATE);
   11596   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   11597 }
   11598 
   11599 
   11600 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
   11601   DCHECK(call->arguments()->length() == 2);
   11602   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11603   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11604   HValue* value = Pop();
   11605   HValue* object = Pop();
   11606 
   11607   // Check if object is a JSValue.
   11608   IfBuilder if_objectisvalue(this);
   11609   if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
   11610   if_objectisvalue.Then();
   11611   {
   11612     // Create in-object property store to kValueOffset.
   11613     Add<HStoreNamedField>(object,
   11614         HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
   11615         value);
   11616     if (!ast_context()->IsEffect()) {
   11617       Push(value);
   11618     }
   11619     Add<HSimulate>(call->id(), FIXED_SIMULATE);
   11620   }
   11621   if_objectisvalue.Else();
   11622   {
   11623     // Nothing to do in this case.
   11624     if (!ast_context()->IsEffect()) {
   11625       Push(value);
   11626     }
   11627     Add<HSimulate>(call->id(), FIXED_SIMULATE);
   11628   }
   11629   if_objectisvalue.End();
   11630   if (!ast_context()->IsEffect()) {
   11631     Drop(1);
   11632   }
   11633   return ast_context()->ReturnValue(value);
   11634 }
   11635 
   11636 
   11637 // Fast support for charCodeAt(n).
   11638 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
   11639   DCHECK(call->arguments()->length() == 2);
   11640   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11641   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11642   HValue* index = Pop();
   11643   HValue* string = Pop();
   11644   HInstruction* result = BuildStringCharCodeAt(string, index);
   11645   return ast_context()->ReturnInstruction(result, call->id());
   11646 }
   11647 
   11648 
   11649 // Fast support for string.charAt(n) and string[n].
   11650 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
   11651   DCHECK(call->arguments()->length() == 1);
   11652   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11653   HValue* char_code = Pop();
   11654   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
   11655   return ast_context()->ReturnInstruction(result, call->id());
   11656 }
   11657 
   11658 
   11659 // Fast support for string.charAt(n) and string[n].
   11660 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
   11661   DCHECK(call->arguments()->length() == 2);
   11662   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11663   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11664   HValue* index = Pop();
   11665   HValue* string = Pop();
   11666   HInstruction* char_code = BuildStringCharCodeAt(string, index);
   11667   AddInstruction(char_code);
   11668   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
   11669   return ast_context()->ReturnInstruction(result, call->id());
   11670 }
   11671 
   11672 
   11673 // Fast support for object equality testing.
   11674 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
   11675   DCHECK(call->arguments()->length() == 2);
   11676   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11677   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11678   HValue* right = Pop();
   11679   HValue* left = Pop();
   11680   HCompareObjectEqAndBranch* result =
   11681       New<HCompareObjectEqAndBranch>(left, right);
   11682   return ast_context()->ReturnControl(result, call->id());
   11683 }
   11684 
   11685 
   11686 // Fast support for StringAdd.
   11687 void HOptimizedGraphBuilder::GenerateStringAdd(CallRuntime* call) {
   11688   DCHECK_EQ(2, call->arguments()->length());
   11689   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11690   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11691   HValue* right = Pop();
   11692   HValue* left = Pop();
   11693   HInstruction* result = NewUncasted<HStringAdd>(left, right);
   11694   return ast_context()->ReturnInstruction(result, call->id());
   11695 }
   11696 
   11697 
   11698 // Fast support for SubString.
   11699 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
   11700   DCHECK_EQ(3, call->arguments()->length());
   11701   CHECK_ALIVE(VisitExpressions(call->arguments()));
   11702   PushArgumentsFromEnvironment(call->arguments()->length());
   11703   HCallStub* result = New<HCallStub>(CodeStub::SubString, 3);
   11704   return ast_context()->ReturnInstruction(result, call->id());
   11705 }
   11706 
   11707 
   11708 // Fast support for StringCompare.
   11709 void HOptimizedGraphBuilder::GenerateStringCompare(CallRuntime* call) {
   11710   DCHECK_EQ(2, call->arguments()->length());
   11711   CHECK_ALIVE(VisitExpressions(call->arguments()));
   11712   PushArgumentsFromEnvironment(call->arguments()->length());
   11713   HCallStub* result = New<HCallStub>(CodeStub::StringCompare, 2);
   11714   return ast_context()->ReturnInstruction(result, call->id());
   11715 }
   11716 
   11717 
   11718 // Support for direct calls from JavaScript to native RegExp code.
   11719 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
   11720   DCHECK_EQ(4, call->arguments()->length());
   11721   CHECK_ALIVE(VisitExpressions(call->arguments()));
   11722   PushArgumentsFromEnvironment(call->arguments()->length());
   11723   HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4);
   11724   return ast_context()->ReturnInstruction(result, call->id());
   11725 }
   11726 
   11727 
   11728 void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) {
   11729   DCHECK_EQ(1, call->arguments()->length());
   11730   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11731   HValue* value = Pop();
   11732   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW);
   11733   return ast_context()->ReturnInstruction(result, call->id());
   11734 }
   11735 
   11736 
   11737 void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) {
   11738   DCHECK_EQ(1, call->arguments()->length());
   11739   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11740   HValue* value = Pop();
   11741   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH);
   11742   return ast_context()->ReturnInstruction(result, call->id());
   11743 }
   11744 
   11745 
   11746 void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) {
   11747   DCHECK_EQ(2, call->arguments()->length());
   11748   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11749   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11750   HValue* lo = Pop();
   11751   HValue* hi = Pop();
   11752   HInstruction* result = NewUncasted<HConstructDouble>(hi, lo);
   11753   return ast_context()->ReturnInstruction(result, call->id());
   11754 }
   11755 
   11756 
   11757 // Construct a RegExp exec result with two in-object properties.
   11758 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
   11759   DCHECK_EQ(3, call->arguments()->length());
   11760   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11761   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11762   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
   11763   HValue* input = Pop();
   11764   HValue* index = Pop();
   11765   HValue* length = Pop();
   11766   HValue* result = BuildRegExpConstructResult(length, index, input);
   11767   return ast_context()->ReturnValue(result);
   11768 }
   11769 
   11770 
   11771 // Support for fast native caches.
   11772 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) {
   11773   return Bailout(kInlinedRuntimeFunctionGetFromCache);
   11774 }
   11775 
   11776 
   11777 // Fast support for number to string.
   11778 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
   11779   DCHECK_EQ(1, call->arguments()->length());
   11780   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11781   HValue* number = Pop();
   11782   HValue* result = BuildNumberToString(number, Type::Any(zone()));
   11783   return ast_context()->ReturnValue(result);
   11784 }
   11785 
   11786 
   11787 // Fast call for custom callbacks.
   11788 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) {
   11789   // 1 ~ The function to call is not itself an argument to the call.
   11790   int arg_count = call->arguments()->length() - 1;
   11791   DCHECK(arg_count >= 1);  // There's always at least a receiver.
   11792 
   11793   CHECK_ALIVE(VisitExpressions(call->arguments()));
   11794   // The function is the last argument
   11795   HValue* function = Pop();
   11796   // Push the arguments to the stack
   11797   PushArgumentsFromEnvironment(arg_count);
   11798 
   11799   IfBuilder if_is_jsfunction(this);
   11800   if_is_jsfunction.If<HHasInstanceTypeAndBranch>(function, JS_FUNCTION_TYPE);
   11801 
   11802   if_is_jsfunction.Then();
   11803   {
   11804     HInstruction* invoke_result =
   11805         Add<HInvokeFunction>(function, arg_count);
   11806     if (!ast_context()->IsEffect()) {
   11807       Push(invoke_result);
   11808     }
   11809     Add<HSimulate>(call->id(), FIXED_SIMULATE);
   11810   }
   11811 
   11812   if_is_jsfunction.Else();
   11813   {
   11814     HInstruction* call_result =
   11815         Add<HCallFunction>(function, arg_count);
   11816     if (!ast_context()->IsEffect()) {
   11817       Push(call_result);
   11818     }
   11819     Add<HSimulate>(call->id(), FIXED_SIMULATE);
   11820   }
   11821   if_is_jsfunction.End();
   11822 
   11823   if (ast_context()->IsEffect()) {
   11824     // EffectContext::ReturnValue ignores the value, so we can just pass
   11825     // 'undefined' (as we do not have the call result anymore).
   11826     return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   11827   } else {
   11828     return ast_context()->ReturnValue(Pop());
   11829   }
   11830 }
   11831 
   11832 
   11833 // Fast call to math functions.
   11834 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
   11835   DCHECK_EQ(2, call->arguments()->length());
   11836   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11837   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   11838   HValue* right = Pop();
   11839   HValue* left = Pop();
   11840   HInstruction* result = NewUncasted<HPower>(left, right);
   11841   return ast_context()->ReturnInstruction(result, call->id());
   11842 }
   11843 
   11844 
   11845 void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
   11846   DCHECK(call->arguments()->length() == 1);
   11847   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11848   HValue* value = Pop();
   11849   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog);
   11850   return ast_context()->ReturnInstruction(result, call->id());
   11851 }
   11852 
   11853 
   11854 void HOptimizedGraphBuilder::GenerateMathSqrtRT(CallRuntime* call) {
   11855   DCHECK(call->arguments()->length() == 1);
   11856   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11857   HValue* value = Pop();
   11858   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
   11859   return ast_context()->ReturnInstruction(result, call->id());
   11860 }
   11861 
   11862 
   11863 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
   11864   DCHECK(call->arguments()->length() == 1);
   11865   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11866   HValue* value = Pop();
   11867   HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
   11868   return ast_context()->ReturnInstruction(result, call->id());
   11869 }
   11870 
   11871 
   11872 void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) {
   11873   return Bailout(kInlinedRuntimeFunctionFastOneByteArrayJoin);
   11874 }
   11875 
   11876 
   11877 // Support for generators.
   11878 void HOptimizedGraphBuilder::GenerateGeneratorNext(CallRuntime* call) {
   11879   return Bailout(kInlinedRuntimeFunctionGeneratorNext);
   11880 }
   11881 
   11882 
   11883 void HOptimizedGraphBuilder::GenerateGeneratorThrow(CallRuntime* call) {
   11884   return Bailout(kInlinedRuntimeFunctionGeneratorThrow);
   11885 }
   11886 
   11887 
   11888 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
   11889     CallRuntime* call) {
   11890   Add<HDebugBreak>();
   11891   return ast_context()->ReturnValue(graph()->GetConstant0());
   11892 }
   11893 
   11894 
   11895 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
   11896   DCHECK(call->arguments()->length() == 0);
   11897   HValue* ref =
   11898       Add<HConstant>(ExternalReference::debug_is_active_address(isolate()));
   11899   HValue* value = Add<HLoadNamedField>(
   11900       ref, static_cast<HValue*>(NULL), HObjectAccess::ForExternalUInteger8());
   11901   return ast_context()->ReturnValue(value);
   11902 }
   11903 
   11904 
   11905 #undef CHECK_BAILOUT
   11906 #undef CHECK_ALIVE
   11907 
   11908 
   11909 HEnvironment::HEnvironment(HEnvironment* outer,
   11910                            Scope* scope,
   11911                            Handle<JSFunction> closure,
   11912                            Zone* zone)
   11913     : closure_(closure),
   11914       values_(0, zone),
   11915       frame_type_(JS_FUNCTION),
   11916       parameter_count_(0),
   11917       specials_count_(1),
   11918       local_count_(0),
   11919       outer_(outer),
   11920       entry_(NULL),
   11921       pop_count_(0),
   11922       push_count_(0),
   11923       ast_id_(BailoutId::None()),
   11924       zone_(zone) {
   11925   Scope* declaration_scope = scope->DeclarationScope();
   11926   Initialize(declaration_scope->num_parameters() + 1,
   11927              declaration_scope->num_stack_slots(), 0);
   11928 }
   11929 
   11930 
   11931 HEnvironment::HEnvironment(Zone* zone, int parameter_count)
   11932     : values_(0, zone),
   11933       frame_type_(STUB),
   11934       parameter_count_(parameter_count),
   11935       specials_count_(1),
   11936       local_count_(0),
   11937       outer_(NULL),
   11938       entry_(NULL),
   11939       pop_count_(0),
   11940       push_count_(0),
   11941       ast_id_(BailoutId::None()),
   11942       zone_(zone) {
   11943   Initialize(parameter_count, 0, 0);
   11944 }
   11945 
   11946 
   11947 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
   11948     : values_(0, zone),
   11949       frame_type_(JS_FUNCTION),
   11950       parameter_count_(0),
   11951       specials_count_(0),
   11952       local_count_(0),
   11953       outer_(NULL),
   11954       entry_(NULL),
   11955       pop_count_(0),
   11956       push_count_(0),
   11957       ast_id_(other->ast_id()),
   11958       zone_(zone) {
   11959   Initialize(other);
   11960 }
   11961 
   11962 
   11963 HEnvironment::HEnvironment(HEnvironment* outer,
   11964                            Handle<JSFunction> closure,
   11965                            FrameType frame_type,
   11966                            int arguments,
   11967                            Zone* zone)
   11968     : closure_(closure),
   11969       values_(arguments, zone),
   11970       frame_type_(frame_type),
   11971       parameter_count_(arguments),
   11972       specials_count_(0),
   11973       local_count_(0),
   11974       outer_(outer),
   11975       entry_(NULL),
   11976       pop_count_(0),
   11977       push_count_(0),
   11978       ast_id_(BailoutId::None()),
   11979       zone_(zone) {
   11980 }
   11981 
   11982 
   11983 void HEnvironment::Initialize(int parameter_count,
   11984                               int local_count,
   11985                               int stack_height) {
   11986   parameter_count_ = parameter_count;
   11987   local_count_ = local_count;
   11988 
   11989   // Avoid reallocating the temporaries' backing store on the first Push.
   11990   int total = parameter_count + specials_count_ + local_count + stack_height;
   11991   values_.Initialize(total + 4, zone());
   11992   for (int i = 0; i < total; ++i) values_.Add(NULL, zone());
   11993 }
   11994 
   11995 
   11996 void HEnvironment::Initialize(const HEnvironment* other) {
   11997   closure_ = other->closure();
   11998   values_.AddAll(other->values_, zone());
   11999   assigned_variables_.Union(other->assigned_variables_, zone());
   12000   frame_type_ = other->frame_type_;
   12001   parameter_count_ = other->parameter_count_;
   12002   local_count_ = other->local_count_;
   12003   if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
   12004   entry_ = other->entry_;
   12005   pop_count_ = other->pop_count_;
   12006   push_count_ = other->push_count_;
   12007   specials_count_ = other->specials_count_;
   12008   ast_id_ = other->ast_id_;
   12009 }
   12010 
   12011 
   12012 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
   12013   DCHECK(!block->IsLoopHeader());
   12014   DCHECK(values_.length() == other->values_.length());
   12015 
   12016   int length = values_.length();
   12017   for (int i = 0; i < length; ++i) {
   12018     HValue* value = values_[i];
   12019     if (value != NULL && value->IsPhi() && value->block() == block) {
   12020       // There is already a phi for the i'th value.
   12021       HPhi* phi = HPhi::cast(value);
   12022       // Assert index is correct and that we haven't missed an incoming edge.
   12023       DCHECK(phi->merged_index() == i || !phi->HasMergedIndex());
   12024       DCHECK(phi->OperandCount() == block->predecessors()->length());
   12025       phi->AddInput(other->values_[i]);
   12026     } else if (values_[i] != other->values_[i]) {
   12027       // There is a fresh value on the incoming edge, a phi is needed.
   12028       DCHECK(values_[i] != NULL && other->values_[i] != NULL);
   12029       HPhi* phi = block->AddNewPhi(i);
   12030       HValue* old_value = values_[i];
   12031       for (int j = 0; j < block->predecessors()->length(); j++) {
   12032         phi->AddInput(old_value);
   12033       }
   12034       phi->AddInput(other->values_[i]);
   12035       this->values_[i] = phi;
   12036     }
   12037   }
   12038 }
   12039 
   12040 
   12041 void HEnvironment::Bind(int index, HValue* value) {
   12042   DCHECK(value != NULL);
   12043   assigned_variables_.Add(index, zone());
   12044   values_[index] = value;
   12045 }
   12046 
   12047 
   12048 bool HEnvironment::HasExpressionAt(int index) const {
   12049   return index >= parameter_count_ + specials_count_ + local_count_;
   12050 }
   12051 
   12052 
   12053 bool HEnvironment::ExpressionStackIsEmpty() const {
   12054   DCHECK(length() >= first_expression_index());
   12055   return length() == first_expression_index();
   12056 }
   12057 
   12058 
   12059 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
   12060   int count = index_from_top + 1;
   12061   int index = values_.length() - count;
   12062   DCHECK(HasExpressionAt(index));
   12063   // The push count must include at least the element in question or else
   12064   // the new value will not be included in this environment's history.
   12065   if (push_count_ < count) {
   12066     // This is the same effect as popping then re-pushing 'count' elements.
   12067     pop_count_ += (count - push_count_);
   12068     push_count_ = count;
   12069   }
   12070   values_[index] = value;
   12071 }
   12072 
   12073 
   12074 void HEnvironment::Drop(int count) {
   12075   for (int i = 0; i < count; ++i) {
   12076     Pop();
   12077   }
   12078 }
   12079 
   12080 
   12081 HEnvironment* HEnvironment::Copy() const {
   12082   return new(zone()) HEnvironment(this, zone());
   12083 }
   12084 
   12085 
   12086 HEnvironment* HEnvironment::CopyWithoutHistory() const {
   12087   HEnvironment* result = Copy();
   12088   result->ClearHistory();
   12089   return result;
   12090 }
   12091 
   12092 
   12093 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
   12094   HEnvironment* new_env = Copy();
   12095   for (int i = 0; i < values_.length(); ++i) {
   12096     HPhi* phi = loop_header->AddNewPhi(i);
   12097     phi->AddInput(values_[i]);
   12098     new_env->values_[i] = phi;
   12099   }
   12100   new_env->ClearHistory();
   12101   return new_env;
   12102 }
   12103 
   12104 
   12105 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
   12106                                                   Handle<JSFunction> target,
   12107                                                   FrameType frame_type,
   12108                                                   int arguments) const {
   12109   HEnvironment* new_env =
   12110       new(zone()) HEnvironment(outer, target, frame_type,
   12111                                arguments + 1, zone());
   12112   for (int i = 0; i <= arguments; ++i) {  // Include receiver.
   12113     new_env->Push(ExpressionStackAt(arguments - i));
   12114   }
   12115   new_env->ClearHistory();
   12116   return new_env;
   12117 }
   12118 
   12119 
   12120 HEnvironment* HEnvironment::CopyForInlining(
   12121     Handle<JSFunction> target,
   12122     int arguments,
   12123     FunctionLiteral* function,
   12124     HConstant* undefined,
   12125     InliningKind inlining_kind) const {
   12126   DCHECK(frame_type() == JS_FUNCTION);
   12127 
   12128   // Outer environment is a copy of this one without the arguments.
   12129   int arity = function->scope()->num_parameters();
   12130 
   12131   HEnvironment* outer = Copy();
   12132   outer->Drop(arguments + 1);  // Including receiver.
   12133   outer->ClearHistory();
   12134 
   12135   if (inlining_kind == CONSTRUCT_CALL_RETURN) {
   12136     // Create artificial constructor stub environment.  The receiver should
   12137     // actually be the constructor function, but we pass the newly allocated
   12138     // object instead, DoComputeConstructStubFrame() relies on that.
   12139     outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
   12140   } else if (inlining_kind == GETTER_CALL_RETURN) {
   12141     // We need an additional StackFrame::INTERNAL frame for restoring the
   12142     // correct context.
   12143     outer = CreateStubEnvironment(outer, target, JS_GETTER, arguments);
   12144   } else if (inlining_kind == SETTER_CALL_RETURN) {
   12145     // We need an additional StackFrame::INTERNAL frame for temporarily saving
   12146     // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
   12147     outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
   12148   }
   12149 
   12150   if (arity != arguments) {
   12151     // Create artificial arguments adaptation environment.
   12152     outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
   12153   }
   12154 
   12155   HEnvironment* inner =
   12156       new(zone()) HEnvironment(outer, function->scope(), target, zone());
   12157   // Get the argument values from the original environment.
   12158   for (int i = 0; i <= arity; ++i) {  // Include receiver.
   12159     HValue* push = (i <= arguments) ?
   12160         ExpressionStackAt(arguments - i) : undefined;
   12161     inner->SetValueAt(i, push);
   12162   }
   12163   inner->SetValueAt(arity + 1, context());
   12164   for (int i = arity + 2; i < inner->length(); ++i) {
   12165     inner->SetValueAt(i, undefined);
   12166   }
   12167 
   12168   inner->set_ast_id(BailoutId::FunctionEntry());
   12169   return inner;
   12170 }
   12171 
   12172 
   12173 OStream& operator<<(OStream& os, const HEnvironment& env) {
   12174   for (int i = 0; i < env.length(); i++) {
   12175     if (i == 0) os << "parameters\n";
   12176     if (i == env.parameter_count()) os << "specials\n";
   12177     if (i == env.parameter_count() + env.specials_count()) os << "locals\n";
   12178     if (i == env.parameter_count() + env.specials_count() + env.local_count()) {
   12179       os << "expressions\n";
   12180     }
   12181     HValue* val = env.values()->at(i);
   12182     os << i << ": ";
   12183     if (val != NULL) {
   12184       os << val;
   12185     } else {
   12186       os << "NULL";
   12187     }
   12188     os << "\n";
   12189   }
   12190   return os << "\n";
   12191 }
   12192 
   12193 
   12194 void HTracer::TraceCompilation(CompilationInfo* info) {
   12195   Tag tag(this, "compilation");
   12196   if (info->IsOptimizing()) {
   12197     Handle<String> name = info->function()->debug_name();
   12198     PrintStringProperty("name", name->ToCString().get());
   12199     PrintIndent();
   12200     trace_.Add("method \"%s:%d\"\n",
   12201                name->ToCString().get(),
   12202                info->optimization_id());
   12203   } else {
   12204     CodeStub::Major major_key = info->code_stub()->MajorKey();
   12205     PrintStringProperty("name", CodeStub::MajorName(major_key, false));
   12206     PrintStringProperty("method", "stub");
   12207   }
   12208   PrintLongProperty("date",
   12209                     static_cast<int64_t>(base::OS::TimeCurrentMillis()));
   12210 }
   12211 
   12212 
   12213 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
   12214   DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
   12215   AllowHandleDereference allow_deref;
   12216   AllowDeferredHandleDereference allow_deferred_deref;
   12217   Trace(name, chunk->graph(), chunk);
   12218 }
   12219 
   12220 
   12221 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
   12222   DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
   12223   AllowHandleDereference allow_deref;
   12224   AllowDeferredHandleDereference allow_deferred_deref;
   12225   Trace(name, graph, NULL);
   12226 }
   12227 
   12228 
   12229 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
   12230   Tag tag(this, "cfg");
   12231   PrintStringProperty("name", name);
   12232   const ZoneList<HBasicBlock*>* blocks = graph->blocks();
   12233   for (int i = 0; i < blocks->length(); i++) {
   12234     HBasicBlock* current = blocks->at(i);
   12235     Tag block_tag(this, "block");
   12236     PrintBlockProperty("name", current->block_id());
   12237     PrintIntProperty("from_bci", -1);
   12238     PrintIntProperty("to_bci", -1);
   12239 
   12240     if (!current->predecessors()->is_empty()) {
   12241       PrintIndent();
   12242       trace_.Add("predecessors");
   12243       for (int j = 0; j < current->predecessors()->length(); ++j) {
   12244         trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
   12245       }
   12246       trace_.Add("\n");
   12247     } else {
   12248       PrintEmptyProperty("predecessors");
   12249     }
   12250 
   12251     if (current->end()->SuccessorCount() == 0) {
   12252       PrintEmptyProperty("successors");
   12253     } else  {
   12254       PrintIndent();
   12255       trace_.Add("successors");
   12256       for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
   12257         trace_.Add(" \"B%d\"", it.Current()->block_id());
   12258       }
   12259       trace_.Add("\n");
   12260     }
   12261 
   12262     PrintEmptyProperty("xhandlers");
   12263 
   12264     {
   12265       PrintIndent();
   12266       trace_.Add("flags");
   12267       if (current->IsLoopSuccessorDominator()) {
   12268         trace_.Add(" \"dom-loop-succ\"");
   12269       }
   12270       if (current->IsUnreachable()) {
   12271         trace_.Add(" \"dead\"");
   12272       }
   12273       if (current->is_osr_entry()) {
   12274         trace_.Add(" \"osr\"");
   12275       }
   12276       trace_.Add("\n");
   12277     }
   12278 
   12279     if (current->dominator() != NULL) {
   12280       PrintBlockProperty("dominator", current->dominator()->block_id());
   12281     }
   12282 
   12283     PrintIntProperty("loop_depth", current->LoopNestingDepth());
   12284 
   12285     if (chunk != NULL) {
   12286       int first_index = current->first_instruction_index();
   12287       int last_index = current->last_instruction_index();
   12288       PrintIntProperty(
   12289           "first_lir_id",
   12290           LifetimePosition::FromInstructionIndex(first_index).Value());
   12291       PrintIntProperty(
   12292           "last_lir_id",
   12293           LifetimePosition::FromInstructionIndex(last_index).Value());
   12294     }
   12295 
   12296     {
   12297       Tag states_tag(this, "states");
   12298       Tag locals_tag(this, "locals");
   12299       int total = current->phis()->length();
   12300       PrintIntProperty("size", current->phis()->length());
   12301       PrintStringProperty("method", "None");
   12302       for (int j = 0; j < total; ++j) {
   12303         HPhi* phi = current->phis()->at(j);
   12304         PrintIndent();
   12305         OStringStream os;
   12306         os << phi->merged_index() << " " << NameOf(phi) << " " << *phi << "\n";
   12307         trace_.Add(os.c_str());
   12308       }
   12309     }
   12310 
   12311     {
   12312       Tag HIR_tag(this, "HIR");
   12313       for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
   12314         HInstruction* instruction = it.Current();
   12315         int uses = instruction->UseCount();
   12316         PrintIndent();
   12317         OStringStream os;
   12318         os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
   12319         if (FLAG_hydrogen_track_positions &&
   12320             instruction->has_position() &&
   12321             instruction->position().raw() != 0) {
   12322           const HSourcePosition pos = instruction->position();
   12323           os << " pos:";
   12324           if (pos.inlining_id() != 0) os << pos.inlining_id() << "_";
   12325           os << pos.position();
   12326         }
   12327         os << " <|@\n";
   12328         trace_.Add(os.c_str());
   12329       }
   12330     }
   12331 
   12332 
   12333     if (chunk != NULL) {
   12334       Tag LIR_tag(this, "LIR");
   12335       int first_index = current->first_instruction_index();
   12336       int last_index = current->last_instruction_index();
   12337       if (first_index != -1 && last_index != -1) {
   12338         const ZoneList<LInstruction*>* instructions = chunk->instructions();
   12339         for (int i = first_index; i <= last_index; ++i) {
   12340           LInstruction* linstr = instructions->at(i);
   12341           if (linstr != NULL) {
   12342             PrintIndent();
   12343             trace_.Add("%d ",
   12344                        LifetimePosition::FromInstructionIndex(i).Value());
   12345             linstr->PrintTo(&trace_);
   12346             OStringStream os;
   12347             os << " [hir:" << NameOf(linstr->hydrogen_value()) << "] <|@\n";
   12348             trace_.Add(os.c_str());
   12349           }
   12350         }
   12351       }
   12352     }
   12353   }
   12354 }
   12355 
   12356 
   12357 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
   12358   Tag tag(this, "intervals");
   12359   PrintStringProperty("name", name);
   12360 
   12361   const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
   12362   for (int i = 0; i < fixed_d->length(); ++i) {
   12363     TraceLiveRange(fixed_d->at(i), "fixed", allocator->zone());
   12364   }
   12365 
   12366   const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
   12367   for (int i = 0; i < fixed->length(); ++i) {
   12368     TraceLiveRange(fixed->at(i), "fixed", allocator->zone());
   12369   }
   12370 
   12371   const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
   12372   for (int i = 0; i < live_ranges->length(); ++i) {
   12373     TraceLiveRange(live_ranges->at(i), "object", allocator->zone());
   12374   }
   12375 }
   12376 
   12377 
   12378 void HTracer::TraceLiveRange(LiveRange* range, const char* type,
   12379                              Zone* zone) {
   12380   if (range != NULL && !range->IsEmpty()) {
   12381     PrintIndent();
   12382     trace_.Add("%d %s", range->id(), type);
   12383     if (range->HasRegisterAssigned()) {
   12384       LOperand* op = range->CreateAssignedOperand(zone);
   12385       int assigned_reg = op->index();
   12386       if (op->IsDoubleRegister()) {
   12387         trace_.Add(" \"%s\"",
   12388                    DoubleRegister::AllocationIndexToString(assigned_reg));
   12389       } else {
   12390         DCHECK(op->IsRegister());
   12391         trace_.Add(" \"%s\"", Register::AllocationIndexToString(assigned_reg));
   12392       }
   12393     } else if (range->IsSpilled()) {
   12394       LOperand* op = range->TopLevel()->GetSpillOperand();
   12395       if (op->IsDoubleStackSlot()) {
   12396         trace_.Add(" \"double_stack:%d\"", op->index());
   12397       } else {
   12398         DCHECK(op->IsStackSlot());
   12399         trace_.Add(" \"stack:%d\"", op->index());
   12400       }
   12401     }
   12402     int parent_index = -1;
   12403     if (range->IsChild()) {
   12404       parent_index = range->parent()->id();
   12405     } else {
   12406       parent_index = range->id();
   12407     }
   12408     LOperand* op = range->FirstHint();
   12409     int hint_index = -1;
   12410     if (op != NULL && op->IsUnallocated()) {
   12411       hint_index = LUnallocated::cast(op)->virtual_register();
   12412     }
   12413     trace_.Add(" %d %d", parent_index, hint_index);
   12414     UseInterval* cur_interval = range->first_interval();
   12415     while (cur_interval != NULL && range->Covers(cur_interval->start())) {
   12416       trace_.Add(" [%d, %d[",
   12417                  cur_interval->start().Value(),
   12418                  cur_interval->end().Value());
   12419       cur_interval = cur_interval->next();
   12420     }
   12421 
   12422     UsePosition* current_pos = range->first_pos();
   12423     while (current_pos != NULL) {
   12424       if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
   12425         trace_.Add(" %d M", current_pos->pos().Value());
   12426       }
   12427       current_pos = current_pos->next();
   12428     }
   12429 
   12430     trace_.Add(" \"\"\n");
   12431   }
   12432 }
   12433 
   12434 
   12435 void HTracer::FlushToFile() {
   12436   AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
   12437               false);
   12438   trace_.Reset();
   12439 }
   12440 
   12441 
   12442 void HStatistics::Initialize(CompilationInfo* info) {
   12443   if (info->shared_info().is_null()) return;
   12444   source_size_ += info->shared_info()->SourceSize();
   12445 }
   12446 
   12447 
   12448 void HStatistics::Print(const char* stats_name) {
   12449   PrintF(
   12450       "\n"
   12451       "----------------------------------------"
   12452       "----------------------------------------\n"
   12453       "--- %s timing results:\n"
   12454       "----------------------------------------"
   12455       "----------------------------------------\n",
   12456       stats_name);
   12457   base::TimeDelta sum;
   12458   for (int i = 0; i < times_.length(); ++i) {
   12459     sum += times_[i];
   12460   }
   12461 
   12462   for (int i = 0; i < names_.length(); ++i) {
   12463     PrintF("%33s", names_[i]);
   12464     double ms = times_[i].InMillisecondsF();
   12465     double percent = times_[i].PercentOf(sum);
   12466     PrintF(" %8.3f ms / %4.1f %% ", ms, percent);
   12467 
   12468     unsigned size = sizes_[i];
   12469     double size_percent = static_cast<double>(size) * 100 / total_size_;
   12470     PrintF(" %9u bytes / %4.1f %%\n", size, size_percent);
   12471   }
   12472 
   12473   PrintF(
   12474       "----------------------------------------"
   12475       "----------------------------------------\n");
   12476   base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
   12477   PrintF("%33s %8.3f ms / %4.1f %% \n", "Create graph",
   12478          create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
   12479   PrintF("%33s %8.3f ms / %4.1f %% \n", "Optimize graph",
   12480          optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
   12481   PrintF("%33s %8.3f ms / %4.1f %% \n", "Generate and install code",
   12482          generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
   12483   PrintF(
   12484       "----------------------------------------"
   12485       "----------------------------------------\n");
   12486   PrintF("%33s %8.3f ms           %9u bytes\n", "Total",
   12487          total.InMillisecondsF(), total_size_);
   12488   PrintF("%33s     (%.1f times slower than full code gen)\n", "",
   12489          total.TimesOf(full_code_gen_));
   12490 
   12491   double source_size_in_kb = static_cast<double>(source_size_) / 1024;
   12492   double normalized_time =  source_size_in_kb > 0
   12493       ? total.InMillisecondsF() / source_size_in_kb
   12494       : 0;
   12495   double normalized_size_in_kb = source_size_in_kb > 0
   12496       ? total_size_ / 1024 / source_size_in_kb
   12497       : 0;
   12498   PrintF("%33s %8.3f ms           %7.3f kB allocated\n",
   12499          "Average per kB source", normalized_time, normalized_size_in_kb);
   12500 }
   12501 
   12502 
   12503 void HStatistics::SaveTiming(const char* name, base::TimeDelta time,
   12504                              unsigned size) {
   12505   total_size_ += size;
   12506   for (int i = 0; i < names_.length(); ++i) {
   12507     if (strcmp(names_[i], name) == 0) {
   12508       times_[i] += time;
   12509       sizes_[i] += size;
   12510       return;
   12511     }
   12512   }
   12513   names_.Add(name);
   12514   times_.Add(time);
   12515   sizes_.Add(size);
   12516 }
   12517 
   12518 
   12519 HPhase::~HPhase() {
   12520   if (ShouldProduceTraceOutput()) {
   12521     isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
   12522   }
   12523 
   12524 #ifdef DEBUG
   12525   graph_->Verify(false);  // No full verify.
   12526 #endif
   12527 }
   12528 
   12529 } }  // namespace v8::internal
   12530