Home | History | Annotate | Download | only in crankshaft
      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/crankshaft/hydrogen.h"
      6 
      7 #include <sstream>
      8 
      9 #include "src/allocation-site-scopes.h"
     10 #include "src/ast/ast-numbering.h"
     11 #include "src/ast/scopeinfo.h"
     12 #include "src/code-factory.h"
     13 #include "src/crankshaft/hydrogen-bce.h"
     14 #include "src/crankshaft/hydrogen-bch.h"
     15 #include "src/crankshaft/hydrogen-canonicalize.h"
     16 #include "src/crankshaft/hydrogen-check-elimination.h"
     17 #include "src/crankshaft/hydrogen-dce.h"
     18 #include "src/crankshaft/hydrogen-dehoist.h"
     19 #include "src/crankshaft/hydrogen-environment-liveness.h"
     20 #include "src/crankshaft/hydrogen-escape-analysis.h"
     21 #include "src/crankshaft/hydrogen-gvn.h"
     22 #include "src/crankshaft/hydrogen-infer-representation.h"
     23 #include "src/crankshaft/hydrogen-infer-types.h"
     24 #include "src/crankshaft/hydrogen-load-elimination.h"
     25 #include "src/crankshaft/hydrogen-mark-deoptimize.h"
     26 #include "src/crankshaft/hydrogen-mark-unreachable.h"
     27 #include "src/crankshaft/hydrogen-osr.h"
     28 #include "src/crankshaft/hydrogen-range-analysis.h"
     29 #include "src/crankshaft/hydrogen-redundant-phi.h"
     30 #include "src/crankshaft/hydrogen-removable-simulates.h"
     31 #include "src/crankshaft/hydrogen-representation-changes.h"
     32 #include "src/crankshaft/hydrogen-sce.h"
     33 #include "src/crankshaft/hydrogen-store-elimination.h"
     34 #include "src/crankshaft/hydrogen-uint32-analysis.h"
     35 #include "src/crankshaft/lithium-allocator.h"
     36 #include "src/crankshaft/typing.h"
     37 #include "src/full-codegen/full-codegen.h"
     38 #include "src/ic/call-optimization.h"
     39 #include "src/ic/ic.h"
     40 // GetRootConstructor
     41 #include "src/ic/ic-inl.h"
     42 #include "src/isolate-inl.h"
     43 #include "src/parsing/parser.h"
     44 #include "src/runtime/runtime.h"
     45 
     46 #if V8_TARGET_ARCH_IA32
     47 #include "src/crankshaft/ia32/lithium-codegen-ia32.h"  // NOLINT
     48 #elif V8_TARGET_ARCH_X64
     49 #include "src/crankshaft/x64/lithium-codegen-x64.h"  // NOLINT
     50 #elif V8_TARGET_ARCH_ARM64
     51 #include "src/crankshaft/arm64/lithium-codegen-arm64.h"  // NOLINT
     52 #elif V8_TARGET_ARCH_ARM
     53 #include "src/crankshaft/arm/lithium-codegen-arm.h"  // NOLINT
     54 #elif V8_TARGET_ARCH_PPC
     55 #include "src/crankshaft/ppc/lithium-codegen-ppc.h"  // NOLINT
     56 #elif V8_TARGET_ARCH_MIPS
     57 #include "src/crankshaft/mips/lithium-codegen-mips.h"  // NOLINT
     58 #elif V8_TARGET_ARCH_MIPS64
     59 #include "src/crankshaft/mips64/lithium-codegen-mips64.h"  // NOLINT
     60 #elif V8_TARGET_ARCH_X87
     61 #include "src/crankshaft/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, SourcePosition position) {
    133   DCHECK(!IsStartBlock() || !IsFinished());
    134   DCHECK(!instr->IsLinked());
    135   DCHECK(!IsFinished());
    136 
    137   if (!position.IsUnknown()) {
    138     instr->set_position(position);
    139   }
    140   if (first_ == NULL) {
    141     DCHECK(last_environment() != NULL);
    142     DCHECK(!last_environment()->ast_id().IsNone());
    143     HBlockEntry* entry = new(zone()) HBlockEntry();
    144     entry->InitializeAsFirst(this);
    145     if (!position.IsUnknown()) {
    146       entry->set_position(position);
    147     } else {
    148       DCHECK(!FLAG_hydrogen_track_positions ||
    149              !graph()->info()->IsOptimizing() || instr->IsAbnormalExit());
    150     }
    151     first_ = last_ = entry;
    152   }
    153   instr->InsertAfter(last_);
    154 }
    155 
    156 
    157 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
    158   if (graph()->IsInsideNoSideEffectsScope()) {
    159     merged_index = HPhi::kInvalidMergedIndex;
    160   }
    161   HPhi* phi = new(zone()) HPhi(merged_index, zone());
    162   AddPhi(phi);
    163   return phi;
    164 }
    165 
    166 
    167 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
    168                                        RemovableSimulate removable) {
    169   DCHECK(HasEnvironment());
    170   HEnvironment* environment = last_environment();
    171   DCHECK(ast_id.IsNone() ||
    172          ast_id == BailoutId::StubEntry() ||
    173          environment->closure()->shared()->VerifyBailoutId(ast_id));
    174 
    175   int push_count = environment->push_count();
    176   int pop_count = environment->pop_count();
    177 
    178   HSimulate* instr =
    179       new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
    180 #ifdef DEBUG
    181   instr->set_closure(environment->closure());
    182 #endif
    183   // Order of pushed values: newest (top of stack) first. This allows
    184   // HSimulate::MergeWith() to easily append additional pushed values
    185   // that are older (from further down the stack).
    186   for (int i = 0; i < push_count; ++i) {
    187     instr->AddPushedValue(environment->ExpressionStackAt(i));
    188   }
    189   for (GrowableBitVector::Iterator it(environment->assigned_variables(),
    190                                       zone());
    191        !it.Done();
    192        it.Advance()) {
    193     int index = it.Current();
    194     instr->AddAssignedValue(index, environment->Lookup(index));
    195   }
    196   environment->ClearHistory();
    197   return instr;
    198 }
    199 
    200 
    201 void HBasicBlock::Finish(HControlInstruction* end, SourcePosition position) {
    202   DCHECK(!IsFinished());
    203   AddInstruction(end, position);
    204   end_ = end;
    205   for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    206     it.Current()->RegisterPredecessor(this);
    207   }
    208 }
    209 
    210 
    211 void HBasicBlock::Goto(HBasicBlock* block, SourcePosition position,
    212                        FunctionState* state, bool add_simulate) {
    213   bool drop_extra = state != NULL &&
    214       state->inlining_kind() == NORMAL_RETURN;
    215 
    216   if (block->IsInlineReturnTarget()) {
    217     HEnvironment* env = last_environment();
    218     int argument_count = env->arguments_environment()->parameter_count();
    219     AddInstruction(new(zone())
    220                    HLeaveInlined(state->entry(), argument_count),
    221                    position);
    222     UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
    223   }
    224 
    225   if (add_simulate) AddNewSimulate(BailoutId::None(), position);
    226   HGoto* instr = new(zone()) HGoto(block);
    227   Finish(instr, position);
    228 }
    229 
    230 
    231 void HBasicBlock::AddLeaveInlined(HValue* return_value, FunctionState* state,
    232                                   SourcePosition position) {
    233   HBasicBlock* target = state->function_return();
    234   bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
    235 
    236   DCHECK(target->IsInlineReturnTarget());
    237   DCHECK(return_value != NULL);
    238   HEnvironment* env = last_environment();
    239   int argument_count = env->arguments_environment()->parameter_count();
    240   AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
    241                  position);
    242   UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
    243   last_environment()->Push(return_value);
    244   AddNewSimulate(BailoutId::None(), position);
    245   HGoto* instr = new(zone()) HGoto(target);
    246   Finish(instr, position);
    247 }
    248 
    249 
    250 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
    251   DCHECK(!HasEnvironment());
    252   DCHECK(first() == NULL);
    253   UpdateEnvironment(env);
    254 }
    255 
    256 
    257 void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
    258   last_environment_ = env;
    259   graph()->update_maximum_environment_size(env->first_expression_index());
    260 }
    261 
    262 
    263 void HBasicBlock::SetJoinId(BailoutId ast_id) {
    264   int length = predecessors_.length();
    265   DCHECK(length > 0);
    266   for (int i = 0; i < length; i++) {
    267     HBasicBlock* predecessor = predecessors_[i];
    268     DCHECK(predecessor->end()->IsGoto());
    269     HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
    270     DCHECK(i != 0 ||
    271            (predecessor->last_environment()->closure().is_null() ||
    272             predecessor->last_environment()->closure()->shared()
    273               ->VerifyBailoutId(ast_id)));
    274     simulate->set_ast_id(ast_id);
    275     predecessor->last_environment()->set_ast_id(ast_id);
    276   }
    277 }
    278 
    279 
    280 bool HBasicBlock::Dominates(HBasicBlock* other) const {
    281   HBasicBlock* current = other->dominator();
    282   while (current != NULL) {
    283     if (current == this) return true;
    284     current = current->dominator();
    285   }
    286   return false;
    287 }
    288 
    289 
    290 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
    291   if (this == other) return true;
    292   return Dominates(other);
    293 }
    294 
    295 
    296 int HBasicBlock::LoopNestingDepth() const {
    297   const HBasicBlock* current = this;
    298   int result  = (current->IsLoopHeader()) ? 1 : 0;
    299   while (current->parent_loop_header() != NULL) {
    300     current = current->parent_loop_header();
    301     result++;
    302   }
    303   return result;
    304 }
    305 
    306 
    307 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
    308   DCHECK(IsLoopHeader());
    309 
    310   SetJoinId(stmt->EntryId());
    311   if (predecessors()->length() == 1) {
    312     // This is a degenerated loop.
    313     DetachLoopInformation();
    314     return;
    315   }
    316 
    317   // Only the first entry into the loop is from outside the loop. All other
    318   // entries must be back edges.
    319   for (int i = 1; i < predecessors()->length(); ++i) {
    320     loop_information()->RegisterBackEdge(predecessors()->at(i));
    321   }
    322 }
    323 
    324 
    325 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
    326   DCHECK(IsFinished());
    327   HBasicBlock* succ_block = end()->SuccessorAt(succ);
    328 
    329   DCHECK(succ_block->predecessors()->length() == 1);
    330   succ_block->MarkUnreachable();
    331 }
    332 
    333 
    334 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
    335   if (HasPredecessor()) {
    336     // Only loop header blocks can have a predecessor added after
    337     // instructions have been added to the block (they have phis for all
    338     // values in the environment, these phis may be eliminated later).
    339     DCHECK(IsLoopHeader() || first_ == NULL);
    340     HEnvironment* incoming_env = pred->last_environment();
    341     if (IsLoopHeader()) {
    342       DCHECK_EQ(phis()->length(), incoming_env->length());
    343       for (int i = 0; i < phis_.length(); ++i) {
    344         phis_[i]->AddInput(incoming_env->values()->at(i));
    345       }
    346     } else {
    347       last_environment()->AddIncomingEdge(this, pred->last_environment());
    348     }
    349   } else if (!HasEnvironment() && !IsFinished()) {
    350     DCHECK(!IsLoopHeader());
    351     SetInitialEnvironment(pred->last_environment()->Copy());
    352   }
    353 
    354   predecessors_.Add(pred, zone());
    355 }
    356 
    357 
    358 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
    359   DCHECK(!dominated_blocks_.Contains(block));
    360   // Keep the list of dominated blocks sorted such that if there is two
    361   // succeeding block in this list, the predecessor is before the successor.
    362   int index = 0;
    363   while (index < dominated_blocks_.length() &&
    364          dominated_blocks_[index]->block_id() < block->block_id()) {
    365     ++index;
    366   }
    367   dominated_blocks_.InsertAt(index, block, zone());
    368 }
    369 
    370 
    371 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
    372   if (dominator_ == NULL) {
    373     dominator_ = other;
    374     other->AddDominatedBlock(this);
    375   } else if (other->dominator() != NULL) {
    376     HBasicBlock* first = dominator_;
    377     HBasicBlock* second = other;
    378 
    379     while (first != second) {
    380       if (first->block_id() > second->block_id()) {
    381         first = first->dominator();
    382       } else {
    383         second = second->dominator();
    384       }
    385       DCHECK(first != NULL && second != NULL);
    386     }
    387 
    388     if (dominator_ != first) {
    389       DCHECK(dominator_->dominated_blocks_.Contains(this));
    390       dominator_->dominated_blocks_.RemoveElement(this);
    391       dominator_ = first;
    392       first->AddDominatedBlock(this);
    393     }
    394   }
    395 }
    396 
    397 
    398 void HBasicBlock::AssignLoopSuccessorDominators() {
    399   // Mark blocks that dominate all subsequent reachable blocks inside their
    400   // loop. Exploit the fact that blocks are sorted in reverse post order. When
    401   // the loop is visited in increasing block id order, if the number of
    402   // non-loop-exiting successor edges at the dominator_candidate block doesn't
    403   // exceed the number of previously encountered predecessor edges, there is no
    404   // path from the loop header to any block with higher id that doesn't go
    405   // through the dominator_candidate block. In this case, the
    406   // dominator_candidate block is guaranteed to dominate all blocks reachable
    407   // from it with higher ids.
    408   HBasicBlock* last = loop_information()->GetLastBackEdge();
    409   int outstanding_successors = 1;  // one edge from the pre-header
    410   // Header always dominates everything.
    411   MarkAsLoopSuccessorDominator();
    412   for (int j = block_id(); j <= last->block_id(); ++j) {
    413     HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
    414     for (HPredecessorIterator it(dominator_candidate); !it.Done();
    415          it.Advance()) {
    416       HBasicBlock* predecessor = it.Current();
    417       // Don't count back edges.
    418       if (predecessor->block_id() < dominator_candidate->block_id()) {
    419         outstanding_successors--;
    420       }
    421     }
    422 
    423     // If more successors than predecessors have been seen in the loop up to
    424     // now, it's not possible to guarantee that the current block dominates
    425     // all of the blocks with higher IDs. In this case, assume conservatively
    426     // that those paths through loop that don't go through the current block
    427     // contain all of the loop's dependencies. Also be careful to record
    428     // dominator information about the current loop that's being processed,
    429     // and not nested loops, which will be processed when
    430     // AssignLoopSuccessorDominators gets called on their header.
    431     DCHECK(outstanding_successors >= 0);
    432     HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
    433     if (outstanding_successors == 0 &&
    434         (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
    435       dominator_candidate->MarkAsLoopSuccessorDominator();
    436     }
    437     HControlInstruction* end = dominator_candidate->end();
    438     for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    439       HBasicBlock* successor = it.Current();
    440       // Only count successors that remain inside the loop and don't loop back
    441       // to a loop header.
    442       if (successor->block_id() > dominator_candidate->block_id() &&
    443           successor->block_id() <= last->block_id()) {
    444         // Backwards edges must land on loop headers.
    445         DCHECK(successor->block_id() > dominator_candidate->block_id() ||
    446                successor->IsLoopHeader());
    447         outstanding_successors++;
    448       }
    449     }
    450   }
    451 }
    452 
    453 
    454 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
    455   for (int i = 0; i < predecessors_.length(); ++i) {
    456     if (predecessors_[i] == predecessor) return i;
    457   }
    458   UNREACHABLE();
    459   return -1;
    460 }
    461 
    462 
    463 #ifdef DEBUG
    464 void HBasicBlock::Verify() {
    465   // Check that every block is finished.
    466   DCHECK(IsFinished());
    467   DCHECK(block_id() >= 0);
    468 
    469   // Check that the incoming edges are in edge split form.
    470   if (predecessors_.length() > 1) {
    471     for (int i = 0; i < predecessors_.length(); ++i) {
    472       DCHECK(predecessors_[i]->end()->SecondSuccessor() == NULL);
    473     }
    474   }
    475 }
    476 #endif
    477 
    478 
    479 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
    480   this->back_edges_.Add(block, block->zone());
    481   AddBlock(block);
    482 }
    483 
    484 
    485 HBasicBlock* HLoopInformation::GetLastBackEdge() const {
    486   int max_id = -1;
    487   HBasicBlock* result = NULL;
    488   for (int i = 0; i < back_edges_.length(); ++i) {
    489     HBasicBlock* cur = back_edges_[i];
    490     if (cur->block_id() > max_id) {
    491       max_id = cur->block_id();
    492       result = cur;
    493     }
    494   }
    495   return result;
    496 }
    497 
    498 
    499 void HLoopInformation::AddBlock(HBasicBlock* block) {
    500   if (block == loop_header()) return;
    501   if (block->parent_loop_header() == loop_header()) return;
    502   if (block->parent_loop_header() != NULL) {
    503     AddBlock(block->parent_loop_header());
    504   } else {
    505     block->set_parent_loop_header(loop_header());
    506     blocks_.Add(block, block->zone());
    507     for (int i = 0; i < block->predecessors()->length(); ++i) {
    508       AddBlock(block->predecessors()->at(i));
    509     }
    510   }
    511 }
    512 
    513 
    514 #ifdef DEBUG
    515 
    516 // Checks reachability of the blocks in this graph and stores a bit in
    517 // the BitVector "reachable()" for every block that can be reached
    518 // from the start block of the graph. If "dont_visit" is non-null, the given
    519 // block is treated as if it would not be part of the graph. "visited_count()"
    520 // returns the number of reachable blocks.
    521 class ReachabilityAnalyzer BASE_EMBEDDED {
    522  public:
    523   ReachabilityAnalyzer(HBasicBlock* entry_block,
    524                        int block_count,
    525                        HBasicBlock* dont_visit)
    526       : visited_count_(0),
    527         stack_(16, entry_block->zone()),
    528         reachable_(block_count, entry_block->zone()),
    529         dont_visit_(dont_visit) {
    530     PushBlock(entry_block);
    531     Analyze();
    532   }
    533 
    534   int visited_count() const { return visited_count_; }
    535   const BitVector* reachable() const { return &reachable_; }
    536 
    537  private:
    538   void PushBlock(HBasicBlock* block) {
    539     if (block != NULL && block != dont_visit_ &&
    540         !reachable_.Contains(block->block_id())) {
    541       reachable_.Add(block->block_id());
    542       stack_.Add(block, block->zone());
    543       visited_count_++;
    544     }
    545   }
    546 
    547   void Analyze() {
    548     while (!stack_.is_empty()) {
    549       HControlInstruction* end = stack_.RemoveLast()->end();
    550       for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    551         PushBlock(it.Current());
    552       }
    553     }
    554   }
    555 
    556   int visited_count_;
    557   ZoneList<HBasicBlock*> stack_;
    558   BitVector reachable_;
    559   HBasicBlock* dont_visit_;
    560 };
    561 
    562 
    563 void HGraph::Verify(bool do_full_verify) const {
    564   Heap::RelocationLock relocation_lock(isolate()->heap());
    565   AllowHandleDereference allow_deref;
    566   AllowDeferredHandleDereference allow_deferred_deref;
    567   for (int i = 0; i < blocks_.length(); i++) {
    568     HBasicBlock* block = blocks_.at(i);
    569 
    570     block->Verify();
    571 
    572     // Check that every block contains at least one node and that only the last
    573     // node is a control instruction.
    574     HInstruction* current = block->first();
    575     DCHECK(current != NULL && current->IsBlockEntry());
    576     while (current != NULL) {
    577       DCHECK((current->next() == NULL) == current->IsControlInstruction());
    578       DCHECK(current->block() == block);
    579       current->Verify();
    580       current = current->next();
    581     }
    582 
    583     // Check that successors are correctly set.
    584     HBasicBlock* first = block->end()->FirstSuccessor();
    585     HBasicBlock* second = block->end()->SecondSuccessor();
    586     DCHECK(second == NULL || first != NULL);
    587 
    588     // Check that the predecessor array is correct.
    589     if (first != NULL) {
    590       DCHECK(first->predecessors()->Contains(block));
    591       if (second != NULL) {
    592         DCHECK(second->predecessors()->Contains(block));
    593       }
    594     }
    595 
    596     // Check that phis have correct arguments.
    597     for (int j = 0; j < block->phis()->length(); j++) {
    598       HPhi* phi = block->phis()->at(j);
    599       phi->Verify();
    600     }
    601 
    602     // Check that all join blocks have predecessors that end with an
    603     // unconditional goto and agree on their environment node id.
    604     if (block->predecessors()->length() >= 2) {
    605       BailoutId id =
    606           block->predecessors()->first()->last_environment()->ast_id();
    607       for (int k = 0; k < block->predecessors()->length(); k++) {
    608         HBasicBlock* predecessor = block->predecessors()->at(k);
    609         DCHECK(predecessor->end()->IsGoto() ||
    610                predecessor->end()->IsDeoptimize());
    611         DCHECK(predecessor->last_environment()->ast_id() == id);
    612       }
    613     }
    614   }
    615 
    616   // Check special property of first block to have no predecessors.
    617   DCHECK(blocks_.at(0)->predecessors()->is_empty());
    618 
    619   if (do_full_verify) {
    620     // Check that the graph is fully connected.
    621     ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
    622     DCHECK(analyzer.visited_count() == blocks_.length());
    623 
    624     // Check that entry block dominator is NULL.
    625     DCHECK(entry_block_->dominator() == NULL);
    626 
    627     // Check dominators.
    628     for (int i = 0; i < blocks_.length(); ++i) {
    629       HBasicBlock* block = blocks_.at(i);
    630       if (block->dominator() == NULL) {
    631         // Only start block may have no dominator assigned to.
    632         DCHECK(i == 0);
    633       } else {
    634         // Assert that block is unreachable if dominator must not be visited.
    635         ReachabilityAnalyzer dominator_analyzer(entry_block_,
    636                                                 blocks_.length(),
    637                                                 block->dominator());
    638         DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id()));
    639       }
    640     }
    641   }
    642 }
    643 
    644 #endif
    645 
    646 
    647 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
    648                                int32_t value) {
    649   if (!pointer->is_set()) {
    650     // Can't pass GetInvalidContext() to HConstant::New, because that will
    651     // recursively call GetConstant
    652     HConstant* constant = HConstant::New(isolate(), zone(), NULL, value);
    653     constant->InsertAfter(entry_block()->first());
    654     pointer->set(constant);
    655     return constant;
    656   }
    657   return ReinsertConstantIfNecessary(pointer->get());
    658 }
    659 
    660 
    661 HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
    662   if (!constant->IsLinked()) {
    663     // The constant was removed from the graph. Reinsert.
    664     constant->ClearFlag(HValue::kIsDead);
    665     constant->InsertAfter(entry_block()->first());
    666   }
    667   return constant;
    668 }
    669 
    670 
    671 HConstant* HGraph::GetConstant0() {
    672   return GetConstant(&constant_0_, 0);
    673 }
    674 
    675 
    676 HConstant* HGraph::GetConstant1() {
    677   return GetConstant(&constant_1_, 1);
    678 }
    679 
    680 
    681 HConstant* HGraph::GetConstantMinus1() {
    682   return GetConstant(&constant_minus1_, -1);
    683 }
    684 
    685 
    686 HConstant* HGraph::GetConstantBool(bool value) {
    687   return value ? GetConstantTrue() : GetConstantFalse();
    688 }
    689 
    690 
    691 #define DEFINE_GET_CONSTANT(Name, name, type, htype, boolean_value)            \
    692 HConstant* HGraph::GetConstant##Name() {                                       \
    693   if (!constant_##name##_.is_set()) {                                          \
    694     HConstant* constant = new(zone()) HConstant(                               \
    695         Unique<Object>::CreateImmovable(isolate()->factory()->name##_value()), \
    696         Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()),      \
    697         false,                                                                 \
    698         Representation::Tagged(),                                              \
    699         htype,                                                                 \
    700         true,                                                                  \
    701         boolean_value,                                                         \
    702         false,                                                                 \
    703         ODDBALL_TYPE);                                                         \
    704     constant->InsertAfter(entry_block()->first());                             \
    705     constant_##name##_.set(constant);                                          \
    706   }                                                                            \
    707   return ReinsertConstantIfNecessary(constant_##name##_.get());                \
    708 }
    709 
    710 
    711 DEFINE_GET_CONSTANT(Undefined, undefined, undefined, HType::Undefined(), false)
    712 DEFINE_GET_CONSTANT(True, true, boolean, HType::Boolean(), true)
    713 DEFINE_GET_CONSTANT(False, false, boolean, HType::Boolean(), false)
    714 DEFINE_GET_CONSTANT(Hole, the_hole, the_hole, HType::None(), false)
    715 DEFINE_GET_CONSTANT(Null, null, null, HType::Null(), false)
    716 
    717 
    718 #undef DEFINE_GET_CONSTANT
    719 
    720 #define DEFINE_IS_CONSTANT(Name, name)                                         \
    721 bool HGraph::IsConstant##Name(HConstant* constant) {                           \
    722   return constant_##name##_.is_set() && constant == constant_##name##_.get();  \
    723 }
    724 DEFINE_IS_CONSTANT(Undefined, undefined)
    725 DEFINE_IS_CONSTANT(0, 0)
    726 DEFINE_IS_CONSTANT(1, 1)
    727 DEFINE_IS_CONSTANT(Minus1, minus1)
    728 DEFINE_IS_CONSTANT(True, true)
    729 DEFINE_IS_CONSTANT(False, false)
    730 DEFINE_IS_CONSTANT(Hole, the_hole)
    731 DEFINE_IS_CONSTANT(Null, null)
    732 
    733 #undef DEFINE_IS_CONSTANT
    734 
    735 
    736 HConstant* HGraph::GetInvalidContext() {
    737   return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
    738 }
    739 
    740 
    741 bool HGraph::IsStandardConstant(HConstant* constant) {
    742   if (IsConstantUndefined(constant)) return true;
    743   if (IsConstant0(constant)) return true;
    744   if (IsConstant1(constant)) return true;
    745   if (IsConstantMinus1(constant)) return true;
    746   if (IsConstantTrue(constant)) return true;
    747   if (IsConstantFalse(constant)) return true;
    748   if (IsConstantHole(constant)) return true;
    749   if (IsConstantNull(constant)) return true;
    750   return false;
    751 }
    752 
    753 
    754 HGraphBuilder::IfBuilder::IfBuilder() : builder_(NULL), needs_compare_(true) {}
    755 
    756 
    757 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
    758     : needs_compare_(true) {
    759   Initialize(builder);
    760 }
    761 
    762 
    763 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
    764                                     HIfContinuation* continuation)
    765     : needs_compare_(false), first_true_block_(NULL), first_false_block_(NULL) {
    766   InitializeDontCreateBlocks(builder);
    767   continuation->Continue(&first_true_block_, &first_false_block_);
    768 }
    769 
    770 
    771 void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
    772     HGraphBuilder* builder) {
    773   builder_ = builder;
    774   finished_ = false;
    775   did_then_ = false;
    776   did_else_ = false;
    777   did_else_if_ = false;
    778   did_and_ = false;
    779   did_or_ = false;
    780   captured_ = false;
    781   pending_merge_block_ = false;
    782   split_edge_merge_block_ = NULL;
    783   merge_at_join_blocks_ = NULL;
    784   normal_merge_at_join_block_count_ = 0;
    785   deopt_merge_at_join_block_count_ = 0;
    786 }
    787 
    788 
    789 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
    790   InitializeDontCreateBlocks(builder);
    791   HEnvironment* env = builder->environment();
    792   first_true_block_ = builder->CreateBasicBlock(env->Copy());
    793   first_false_block_ = builder->CreateBasicBlock(env->Copy());
    794 }
    795 
    796 
    797 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
    798     HControlInstruction* compare) {
    799   DCHECK(did_then_ == did_else_);
    800   if (did_else_) {
    801     // Handle if-then-elseif
    802     did_else_if_ = true;
    803     did_else_ = false;
    804     did_then_ = false;
    805     did_and_ = false;
    806     did_or_ = false;
    807     pending_merge_block_ = false;
    808     split_edge_merge_block_ = NULL;
    809     HEnvironment* env = builder()->environment();
    810     first_true_block_ = builder()->CreateBasicBlock(env->Copy());
    811     first_false_block_ = builder()->CreateBasicBlock(env->Copy());
    812   }
    813   if (split_edge_merge_block_ != NULL) {
    814     HEnvironment* env = first_false_block_->last_environment();
    815     HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
    816     if (did_or_) {
    817       compare->SetSuccessorAt(0, split_edge);
    818       compare->SetSuccessorAt(1, first_false_block_);
    819     } else {
    820       compare->SetSuccessorAt(0, first_true_block_);
    821       compare->SetSuccessorAt(1, split_edge);
    822     }
    823     builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
    824   } else {
    825     compare->SetSuccessorAt(0, first_true_block_);
    826     compare->SetSuccessorAt(1, first_false_block_);
    827   }
    828   builder()->FinishCurrentBlock(compare);
    829   needs_compare_ = false;
    830   return compare;
    831 }
    832 
    833 
    834 void HGraphBuilder::IfBuilder::Or() {
    835   DCHECK(!needs_compare_);
    836   DCHECK(!did_and_);
    837   did_or_ = true;
    838   HEnvironment* env = first_false_block_->last_environment();
    839   if (split_edge_merge_block_ == NULL) {
    840     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
    841     builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
    842     first_true_block_ = split_edge_merge_block_;
    843   }
    844   builder()->set_current_block(first_false_block_);
    845   first_false_block_ = builder()->CreateBasicBlock(env->Copy());
    846 }
    847 
    848 
    849 void HGraphBuilder::IfBuilder::And() {
    850   DCHECK(!needs_compare_);
    851   DCHECK(!did_or_);
    852   did_and_ = true;
    853   HEnvironment* env = first_false_block_->last_environment();
    854   if (split_edge_merge_block_ == NULL) {
    855     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
    856     builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
    857     first_false_block_ = split_edge_merge_block_;
    858   }
    859   builder()->set_current_block(first_true_block_);
    860   first_true_block_ = builder()->CreateBasicBlock(env->Copy());
    861 }
    862 
    863 
    864 void HGraphBuilder::IfBuilder::CaptureContinuation(
    865     HIfContinuation* continuation) {
    866   DCHECK(!did_else_if_);
    867   DCHECK(!finished_);
    868   DCHECK(!captured_);
    869 
    870   HBasicBlock* true_block = NULL;
    871   HBasicBlock* false_block = NULL;
    872   Finish(&true_block, &false_block);
    873   DCHECK(true_block != NULL);
    874   DCHECK(false_block != NULL);
    875   continuation->Capture(true_block, false_block);
    876   captured_ = true;
    877   builder()->set_current_block(NULL);
    878   End();
    879 }
    880 
    881 
    882 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
    883   DCHECK(!did_else_if_);
    884   DCHECK(!finished_);
    885   DCHECK(!captured_);
    886   HBasicBlock* true_block = NULL;
    887   HBasicBlock* false_block = NULL;
    888   Finish(&true_block, &false_block);
    889   merge_at_join_blocks_ = NULL;
    890   if (true_block != NULL && !true_block->IsFinished()) {
    891     DCHECK(continuation->IsTrueReachable());
    892     builder()->GotoNoSimulate(true_block, continuation->true_branch());
    893   }
    894   if (false_block != NULL && !false_block->IsFinished()) {
    895     DCHECK(continuation->IsFalseReachable());
    896     builder()->GotoNoSimulate(false_block, continuation->false_branch());
    897   }
    898   captured_ = true;
    899   End();
    900 }
    901 
    902 
    903 void HGraphBuilder::IfBuilder::Then() {
    904   DCHECK(!captured_);
    905   DCHECK(!finished_);
    906   did_then_ = true;
    907   if (needs_compare_) {
    908     // Handle if's without any expressions, they jump directly to the "else"
    909     // branch. However, we must pretend that the "then" branch is reachable,
    910     // so that the graph builder visits it and sees any live range extending
    911     // constructs within it.
    912     HConstant* constant_false = builder()->graph()->GetConstantFalse();
    913     ToBooleanStub::Types boolean_type = ToBooleanStub::Types();
    914     boolean_type.Add(ToBooleanStub::BOOLEAN);
    915     HBranch* branch = builder()->New<HBranch>(
    916         constant_false, boolean_type, first_true_block_, first_false_block_);
    917     builder()->FinishCurrentBlock(branch);
    918   }
    919   builder()->set_current_block(first_true_block_);
    920   pending_merge_block_ = true;
    921 }
    922 
    923 
    924 void HGraphBuilder::IfBuilder::Else() {
    925   DCHECK(did_then_);
    926   DCHECK(!captured_);
    927   DCHECK(!finished_);
    928   AddMergeAtJoinBlock(false);
    929   builder()->set_current_block(first_false_block_);
    930   pending_merge_block_ = true;
    931   did_else_ = true;
    932 }
    933 
    934 
    935 void HGraphBuilder::IfBuilder::Deopt(Deoptimizer::DeoptReason reason) {
    936   DCHECK(did_then_);
    937   builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
    938   AddMergeAtJoinBlock(true);
    939 }
    940 
    941 
    942 void HGraphBuilder::IfBuilder::Return(HValue* value) {
    943   HValue* parameter_count = builder()->graph()->GetConstantMinus1();
    944   builder()->FinishExitCurrentBlock(
    945       builder()->New<HReturn>(value, parameter_count));
    946   AddMergeAtJoinBlock(false);
    947 }
    948 
    949 
    950 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
    951   if (!pending_merge_block_) return;
    952   HBasicBlock* block = builder()->current_block();
    953   DCHECK(block == NULL || !block->IsFinished());
    954   MergeAtJoinBlock* record = new (builder()->zone())
    955       MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
    956   merge_at_join_blocks_ = record;
    957   if (block != NULL) {
    958     DCHECK(block->end() == NULL);
    959     if (deopt) {
    960       normal_merge_at_join_block_count_++;
    961     } else {
    962       deopt_merge_at_join_block_count_++;
    963     }
    964   }
    965   builder()->set_current_block(NULL);
    966   pending_merge_block_ = false;
    967 }
    968 
    969 
    970 void HGraphBuilder::IfBuilder::Finish() {
    971   DCHECK(!finished_);
    972   if (!did_then_) {
    973     Then();
    974   }
    975   AddMergeAtJoinBlock(false);
    976   if (!did_else_) {
    977     Else();
    978     AddMergeAtJoinBlock(false);
    979   }
    980   finished_ = true;
    981 }
    982 
    983 
    984 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
    985                                       HBasicBlock** else_continuation) {
    986   Finish();
    987 
    988   MergeAtJoinBlock* else_record = merge_at_join_blocks_;
    989   if (else_continuation != NULL) {
    990     *else_continuation = else_record->block_;
    991   }
    992   MergeAtJoinBlock* then_record = else_record->next_;
    993   if (then_continuation != NULL) {
    994     *then_continuation = then_record->block_;
    995   }
    996   DCHECK(then_record->next_ == NULL);
    997 }
    998 
    999 
   1000 void HGraphBuilder::IfBuilder::EndUnreachable() {
   1001   if (captured_) return;
   1002   Finish();
   1003   builder()->set_current_block(nullptr);
   1004 }
   1005 
   1006 
   1007 void HGraphBuilder::IfBuilder::End() {
   1008   if (captured_) return;
   1009   Finish();
   1010 
   1011   int total_merged_blocks = normal_merge_at_join_block_count_ +
   1012     deopt_merge_at_join_block_count_;
   1013   DCHECK(total_merged_blocks >= 1);
   1014   HBasicBlock* merge_block =
   1015       total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock();
   1016 
   1017   // Merge non-deopt blocks first to ensure environment has right size for
   1018   // padding.
   1019   MergeAtJoinBlock* current = merge_at_join_blocks_;
   1020   while (current != NULL) {
   1021     if (!current->deopt_ && current->block_ != NULL) {
   1022       // If there is only one block that makes it through to the end of the
   1023       // if, then just set it as the current block and continue rather then
   1024       // creating an unnecessary merge block.
   1025       if (total_merged_blocks == 1) {
   1026         builder()->set_current_block(current->block_);
   1027         return;
   1028       }
   1029       builder()->GotoNoSimulate(current->block_, merge_block);
   1030     }
   1031     current = current->next_;
   1032   }
   1033 
   1034   // Merge deopt blocks, padding when necessary.
   1035   current = merge_at_join_blocks_;
   1036   while (current != NULL) {
   1037     if (current->deopt_ && current->block_ != NULL) {
   1038       current->block_->FinishExit(
   1039           HAbnormalExit::New(builder()->isolate(), builder()->zone(), NULL),
   1040           SourcePosition::Unknown());
   1041     }
   1042     current = current->next_;
   1043   }
   1044   builder()->set_current_block(merge_block);
   1045 }
   1046 
   1047 
   1048 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
   1049   Initialize(builder, NULL, kWhileTrue, NULL);
   1050 }
   1051 
   1052 
   1053 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
   1054                                         LoopBuilder::Direction direction) {
   1055   Initialize(builder, context, direction, builder->graph()->GetConstant1());
   1056 }
   1057 
   1058 
   1059 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
   1060                                         LoopBuilder::Direction direction,
   1061                                         HValue* increment_amount) {
   1062   Initialize(builder, context, direction, increment_amount);
   1063   increment_amount_ = increment_amount;
   1064 }
   1065 
   1066 
   1067 void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
   1068                                             HValue* context,
   1069                                             Direction direction,
   1070                                             HValue* increment_amount) {
   1071   builder_ = builder;
   1072   context_ = context;
   1073   direction_ = direction;
   1074   increment_amount_ = increment_amount;
   1075 
   1076   finished_ = false;
   1077   header_block_ = builder->CreateLoopHeaderBlock();
   1078   body_block_ = NULL;
   1079   exit_block_ = NULL;
   1080   exit_trampoline_block_ = NULL;
   1081 }
   1082 
   1083 
   1084 HValue* HGraphBuilder::LoopBuilder::BeginBody(
   1085     HValue* initial,
   1086     HValue* terminating,
   1087     Token::Value token) {
   1088   DCHECK(direction_ != kWhileTrue);
   1089   HEnvironment* env = builder_->environment();
   1090   phi_ = header_block_->AddNewPhi(env->values()->length());
   1091   phi_->AddInput(initial);
   1092   env->Push(initial);
   1093   builder_->GotoNoSimulate(header_block_);
   1094 
   1095   HEnvironment* body_env = env->Copy();
   1096   HEnvironment* exit_env = env->Copy();
   1097   // Remove the phi from the expression stack
   1098   body_env->Pop();
   1099   exit_env->Pop();
   1100   body_block_ = builder_->CreateBasicBlock(body_env);
   1101   exit_block_ = builder_->CreateBasicBlock(exit_env);
   1102 
   1103   builder_->set_current_block(header_block_);
   1104   env->Pop();
   1105   builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
   1106           phi_, terminating, token, body_block_, exit_block_));
   1107 
   1108   builder_->set_current_block(body_block_);
   1109   if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
   1110     Isolate* isolate = builder_->isolate();
   1111     HValue* one = builder_->graph()->GetConstant1();
   1112     if (direction_ == kPreIncrement) {
   1113       increment_ = HAdd::New(isolate, zone(), context_, phi_, one);
   1114     } else {
   1115       increment_ = HSub::New(isolate, zone(), context_, phi_, one);
   1116     }
   1117     increment_->ClearFlag(HValue::kCanOverflow);
   1118     builder_->AddInstruction(increment_);
   1119     return increment_;
   1120   } else {
   1121     return phi_;
   1122   }
   1123 }
   1124 
   1125 
   1126 void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) {
   1127   DCHECK(direction_ == kWhileTrue);
   1128   HEnvironment* env = builder_->environment();
   1129   builder_->GotoNoSimulate(header_block_);
   1130   builder_->set_current_block(header_block_);
   1131   env->Drop(drop_count);
   1132 }
   1133 
   1134 
   1135 void HGraphBuilder::LoopBuilder::Break() {
   1136   if (exit_trampoline_block_ == NULL) {
   1137     // Its the first time we saw a break.
   1138     if (direction_ == kWhileTrue) {
   1139       HEnvironment* env = builder_->environment()->Copy();
   1140       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
   1141     } else {
   1142       HEnvironment* env = exit_block_->last_environment()->Copy();
   1143       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
   1144       builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
   1145     }
   1146   }
   1147 
   1148   builder_->GotoNoSimulate(exit_trampoline_block_);
   1149   builder_->set_current_block(NULL);
   1150 }
   1151 
   1152 
   1153 void HGraphBuilder::LoopBuilder::EndBody() {
   1154   DCHECK(!finished_);
   1155 
   1156   if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
   1157     Isolate* isolate = builder_->isolate();
   1158     if (direction_ == kPostIncrement) {
   1159       increment_ =
   1160           HAdd::New(isolate, zone(), context_, phi_, increment_amount_);
   1161     } else {
   1162       increment_ =
   1163           HSub::New(isolate, zone(), context_, phi_, increment_amount_);
   1164     }
   1165     increment_->ClearFlag(HValue::kCanOverflow);
   1166     builder_->AddInstruction(increment_);
   1167   }
   1168 
   1169   if (direction_ != kWhileTrue) {
   1170     // Push the new increment value on the expression stack to merge into
   1171     // the phi.
   1172     builder_->environment()->Push(increment_);
   1173   }
   1174   HBasicBlock* last_block = builder_->current_block();
   1175   builder_->GotoNoSimulate(last_block, header_block_);
   1176   header_block_->loop_information()->RegisterBackEdge(last_block);
   1177 
   1178   if (exit_trampoline_block_ != NULL) {
   1179     builder_->set_current_block(exit_trampoline_block_);
   1180   } else {
   1181     builder_->set_current_block(exit_block_);
   1182   }
   1183   finished_ = true;
   1184 }
   1185 
   1186 
   1187 HGraph* HGraphBuilder::CreateGraph() {
   1188   graph_ = new(zone()) HGraph(info_);
   1189   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
   1190   CompilationPhase phase("H_Block building", info_);
   1191   set_current_block(graph()->entry_block());
   1192   if (!BuildGraph()) return NULL;
   1193   graph()->FinalizeUniqueness();
   1194   return graph_;
   1195 }
   1196 
   1197 
   1198 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
   1199   DCHECK(current_block() != NULL);
   1200   DCHECK(!FLAG_hydrogen_track_positions ||
   1201          !position_.IsUnknown() ||
   1202          !info_->IsOptimizing());
   1203   current_block()->AddInstruction(instr, source_position());
   1204   if (graph()->IsInsideNoSideEffectsScope()) {
   1205     instr->SetFlag(HValue::kHasNoObservableSideEffects);
   1206   }
   1207   return instr;
   1208 }
   1209 
   1210 
   1211 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
   1212   DCHECK(!FLAG_hydrogen_track_positions ||
   1213          !info_->IsOptimizing() ||
   1214          !position_.IsUnknown());
   1215   current_block()->Finish(last, source_position());
   1216   if (last->IsReturn() || last->IsAbnormalExit()) {
   1217     set_current_block(NULL);
   1218   }
   1219 }
   1220 
   1221 
   1222 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
   1223   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
   1224          !position_.IsUnknown());
   1225   current_block()->FinishExit(instruction, source_position());
   1226   if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
   1227     set_current_block(NULL);
   1228   }
   1229 }
   1230 
   1231 
   1232 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
   1233   if (FLAG_native_code_counters && counter->Enabled()) {
   1234     HValue* reference = Add<HConstant>(ExternalReference(counter));
   1235     HValue* old_value =
   1236         Add<HLoadNamedField>(reference, nullptr, HObjectAccess::ForCounter());
   1237     HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
   1238     new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
   1239     Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
   1240                           new_value, STORE_TO_INITIALIZED_ENTRY);
   1241   }
   1242 }
   1243 
   1244 
   1245 void HGraphBuilder::AddSimulate(BailoutId id,
   1246                                 RemovableSimulate removable) {
   1247   DCHECK(current_block() != NULL);
   1248   DCHECK(!graph()->IsInsideNoSideEffectsScope());
   1249   current_block()->AddNewSimulate(id, source_position(), removable);
   1250 }
   1251 
   1252 
   1253 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
   1254   HBasicBlock* b = graph()->CreateBasicBlock();
   1255   b->SetInitialEnvironment(env);
   1256   return b;
   1257 }
   1258 
   1259 
   1260 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
   1261   HBasicBlock* header = graph()->CreateBasicBlock();
   1262   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
   1263   header->SetInitialEnvironment(entry_env);
   1264   header->AttachLoopInformation();
   1265   return header;
   1266 }
   1267 
   1268 
   1269 HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) {
   1270   HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
   1271 
   1272   HValue* bit_field2 =
   1273       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
   1274   return BuildDecodeField<Map::ElementsKindBits>(bit_field2);
   1275 }
   1276 
   1277 
   1278 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
   1279   if (obj->type().IsHeapObject()) return obj;
   1280   return Add<HCheckHeapObject>(obj);
   1281 }
   1282 
   1283 
   1284 void HGraphBuilder::FinishExitWithHardDeoptimization(
   1285     Deoptimizer::DeoptReason reason) {
   1286   Add<HDeoptimize>(reason, Deoptimizer::EAGER);
   1287   FinishExitCurrentBlock(New<HAbnormalExit>());
   1288 }
   1289 
   1290 
   1291 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
   1292   if (!string->type().IsString()) {
   1293     DCHECK(!string->IsConstant() ||
   1294            !HConstant::cast(string)->HasStringValue());
   1295     BuildCheckHeapObject(string);
   1296     return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
   1297   }
   1298   return string;
   1299 }
   1300 
   1301 
   1302 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* function) {
   1303   if (object->type().IsJSObject()) return object;
   1304   if (function->IsConstant() &&
   1305       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   1306     Handle<JSFunction> f = Handle<JSFunction>::cast(
   1307         HConstant::cast(function)->handle(isolate()));
   1308     SharedFunctionInfo* shared = f->shared();
   1309     if (is_strict(shared->language_mode()) || shared->native()) return object;
   1310   }
   1311   return Add<HWrapReceiver>(object, function);
   1312 }
   1313 
   1314 
   1315 HValue* HGraphBuilder::BuildCheckAndGrowElementsCapacity(
   1316     HValue* object, HValue* elements, ElementsKind kind, HValue* length,
   1317     HValue* capacity, HValue* key) {
   1318   HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
   1319   HValue* max_capacity = AddUncasted<HAdd>(capacity, max_gap);
   1320   Add<HBoundsCheck>(key, max_capacity);
   1321 
   1322   HValue* new_capacity = BuildNewElementsCapacity(key);
   1323   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind, kind,
   1324                                                    length, new_capacity);
   1325   return new_elements;
   1326 }
   1327 
   1328 
   1329 HValue* HGraphBuilder::BuildCheckForCapacityGrow(
   1330     HValue* object,
   1331     HValue* elements,
   1332     ElementsKind kind,
   1333     HValue* length,
   1334     HValue* key,
   1335     bool is_js_array,
   1336     PropertyAccessType access_type) {
   1337   IfBuilder length_checker(this);
   1338 
   1339   Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
   1340   length_checker.If<HCompareNumericAndBranch>(key, length, token);
   1341 
   1342   length_checker.Then();
   1343 
   1344   HValue* current_capacity = AddLoadFixedArrayLength(elements);
   1345 
   1346   if (top_info()->IsStub()) {
   1347     IfBuilder capacity_checker(this);
   1348     capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
   1349                                                   Token::GTE);
   1350     capacity_checker.Then();
   1351     HValue* new_elements = BuildCheckAndGrowElementsCapacity(
   1352         object, elements, kind, length, current_capacity, key);
   1353     environment()->Push(new_elements);
   1354     capacity_checker.Else();
   1355     environment()->Push(elements);
   1356     capacity_checker.End();
   1357   } else {
   1358     HValue* result = Add<HMaybeGrowElements>(
   1359         object, elements, key, current_capacity, is_js_array, kind);
   1360     environment()->Push(result);
   1361   }
   1362 
   1363   if (is_js_array) {
   1364     HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
   1365     new_length->ClearFlag(HValue::kCanOverflow);
   1366 
   1367     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
   1368                           new_length);
   1369   }
   1370 
   1371   if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
   1372     HValue* checked_elements = environment()->Top();
   1373 
   1374     // Write zero to ensure that the new element is initialized with some smi.
   1375     Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), nullptr,
   1376                      kind);
   1377   }
   1378 
   1379   length_checker.Else();
   1380   Add<HBoundsCheck>(key, length);
   1381 
   1382   environment()->Push(elements);
   1383   length_checker.End();
   1384 
   1385   return environment()->Pop();
   1386 }
   1387 
   1388 
   1389 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
   1390                                                 HValue* elements,
   1391                                                 ElementsKind kind,
   1392                                                 HValue* length) {
   1393   Factory* factory = isolate()->factory();
   1394 
   1395   IfBuilder cow_checker(this);
   1396 
   1397   cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
   1398   cow_checker.Then();
   1399 
   1400   HValue* capacity = AddLoadFixedArrayLength(elements);
   1401 
   1402   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
   1403                                                    kind, length, capacity);
   1404 
   1405   environment()->Push(new_elements);
   1406 
   1407   cow_checker.Else();
   1408 
   1409   environment()->Push(elements);
   1410 
   1411   cow_checker.End();
   1412 
   1413   return environment()->Pop();
   1414 }
   1415 
   1416 
   1417 void HGraphBuilder::BuildTransitionElementsKind(HValue* object,
   1418                                                 HValue* map,
   1419                                                 ElementsKind from_kind,
   1420                                                 ElementsKind to_kind,
   1421                                                 bool is_jsarray) {
   1422   DCHECK(!IsFastHoleyElementsKind(from_kind) ||
   1423          IsFastHoleyElementsKind(to_kind));
   1424 
   1425   if (AllocationSite::GetMode(from_kind, to_kind) == TRACK_ALLOCATION_SITE) {
   1426     Add<HTrapAllocationMemento>(object);
   1427   }
   1428 
   1429   if (!IsSimpleMapChangeTransition(from_kind, to_kind)) {
   1430     HInstruction* elements = AddLoadElements(object);
   1431 
   1432     HInstruction* empty_fixed_array = Add<HConstant>(
   1433         isolate()->factory()->empty_fixed_array());
   1434 
   1435     IfBuilder if_builder(this);
   1436 
   1437     if_builder.IfNot<HCompareObjectEqAndBranch>(elements, empty_fixed_array);
   1438 
   1439     if_builder.Then();
   1440 
   1441     HInstruction* elements_length = AddLoadFixedArrayLength(elements);
   1442 
   1443     HInstruction* array_length =
   1444         is_jsarray
   1445             ? Add<HLoadNamedField>(object, nullptr,
   1446                                    HObjectAccess::ForArrayLength(from_kind))
   1447             : elements_length;
   1448 
   1449     BuildGrowElementsCapacity(object, elements, from_kind, to_kind,
   1450                               array_length, elements_length);
   1451 
   1452     if_builder.End();
   1453   }
   1454 
   1455   Add<HStoreNamedField>(object, HObjectAccess::ForMap(), map);
   1456 }
   1457 
   1458 
   1459 void HGraphBuilder::BuildJSObjectCheck(HValue* receiver,
   1460                                        int bit_field_mask) {
   1461   // Check that the object isn't a smi.
   1462   Add<HCheckHeapObject>(receiver);
   1463 
   1464   // Get the map of the receiver.
   1465   HValue* map =
   1466       Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
   1467 
   1468   // Check the instance type and if an access check is needed, this can be
   1469   // done with a single load, since both bytes are adjacent in the map.
   1470   HObjectAccess access(HObjectAccess::ForMapInstanceTypeAndBitField());
   1471   HValue* instance_type_and_bit_field =
   1472       Add<HLoadNamedField>(map, nullptr, access);
   1473 
   1474   HValue* mask = Add<HConstant>(0x00FF | (bit_field_mask << 8));
   1475   HValue* and_result = AddUncasted<HBitwise>(Token::BIT_AND,
   1476                                              instance_type_and_bit_field,
   1477                                              mask);
   1478   HValue* sub_result = AddUncasted<HSub>(and_result,
   1479                                          Add<HConstant>(JS_OBJECT_TYPE));
   1480   Add<HBoundsCheck>(sub_result,
   1481                     Add<HConstant>(LAST_JS_OBJECT_TYPE + 1 - JS_OBJECT_TYPE));
   1482 }
   1483 
   1484 
   1485 void HGraphBuilder::BuildKeyedIndexCheck(HValue* key,
   1486                                          HIfContinuation* join_continuation) {
   1487   // The sometimes unintuitively backward ordering of the ifs below is
   1488   // convoluted, but necessary.  All of the paths must guarantee that the
   1489   // if-true of the continuation returns a smi element index and the if-false of
   1490   // the continuation returns either a symbol or a unique string key. All other
   1491   // object types cause a deopt to fall back to the runtime.
   1492 
   1493   IfBuilder key_smi_if(this);
   1494   key_smi_if.If<HIsSmiAndBranch>(key);
   1495   key_smi_if.Then();
   1496   {
   1497     Push(key);  // Nothing to do, just continue to true of continuation.
   1498   }
   1499   key_smi_if.Else();
   1500   {
   1501     HValue* map = Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForMap());
   1502     HValue* instance_type =
   1503         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
   1504 
   1505     // Non-unique string, check for a string with a hash code that is actually
   1506     // an index.
   1507     STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE);
   1508     IfBuilder not_string_or_name_if(this);
   1509     not_string_or_name_if.If<HCompareNumericAndBranch>(
   1510         instance_type,
   1511         Add<HConstant>(LAST_UNIQUE_NAME_TYPE),
   1512         Token::GT);
   1513 
   1514     not_string_or_name_if.Then();
   1515     {
   1516       // Non-smi, non-Name, non-String: Try to convert to smi in case of
   1517       // HeapNumber.
   1518       // TODO(danno): This could call some variant of ToString
   1519       Push(AddUncasted<HForceRepresentation>(key, Representation::Smi()));
   1520     }
   1521     not_string_or_name_if.Else();
   1522     {
   1523       // String or Name: check explicitly for Name, they can short-circuit
   1524       // directly to unique non-index key path.
   1525       IfBuilder not_symbol_if(this);
   1526       not_symbol_if.If<HCompareNumericAndBranch>(
   1527           instance_type,
   1528           Add<HConstant>(SYMBOL_TYPE),
   1529           Token::NE);
   1530 
   1531       not_symbol_if.Then();
   1532       {
   1533         // String: check whether the String is a String of an index. If it is,
   1534         // extract the index value from the hash.
   1535         HValue* hash = Add<HLoadNamedField>(key, nullptr,
   1536                                             HObjectAccess::ForNameHashField());
   1537         HValue* not_index_mask = Add<HConstant>(static_cast<int>(
   1538             String::kContainsCachedArrayIndexMask));
   1539 
   1540         HValue* not_index_test = AddUncasted<HBitwise>(
   1541             Token::BIT_AND, hash, not_index_mask);
   1542 
   1543         IfBuilder string_index_if(this);
   1544         string_index_if.If<HCompareNumericAndBranch>(not_index_test,
   1545                                                      graph()->GetConstant0(),
   1546                                                      Token::EQ);
   1547         string_index_if.Then();
   1548         {
   1549           // String with index in hash: extract string and merge to index path.
   1550           Push(BuildDecodeField<String::ArrayIndexValueBits>(hash));
   1551         }
   1552         string_index_if.Else();
   1553         {
   1554           // Key is a non-index String, check for uniqueness/internalization.
   1555           // If it's not internalized yet, internalize it now.
   1556           HValue* not_internalized_bit = AddUncasted<HBitwise>(
   1557               Token::BIT_AND,
   1558               instance_type,
   1559               Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
   1560 
   1561           IfBuilder internalized(this);
   1562           internalized.If<HCompareNumericAndBranch>(not_internalized_bit,
   1563                                                     graph()->GetConstant0(),
   1564                                                     Token::EQ);
   1565           internalized.Then();
   1566           Push(key);
   1567 
   1568           internalized.Else();
   1569           Add<HPushArguments>(key);
   1570           HValue* intern_key = Add<HCallRuntime>(
   1571               Runtime::FunctionForId(Runtime::kInternalizeString), 1);
   1572           Push(intern_key);
   1573 
   1574           internalized.End();
   1575           // Key guaranteed to be a unique string
   1576         }
   1577         string_index_if.JoinContinuation(join_continuation);
   1578       }
   1579       not_symbol_if.Else();
   1580       {
   1581         Push(key);  // Key is symbol
   1582       }
   1583       not_symbol_if.JoinContinuation(join_continuation);
   1584     }
   1585     not_string_or_name_if.JoinContinuation(join_continuation);
   1586   }
   1587   key_smi_if.JoinContinuation(join_continuation);
   1588 }
   1589 
   1590 
   1591 void HGraphBuilder::BuildNonGlobalObjectCheck(HValue* receiver) {
   1592   // Get the the instance type of the receiver, and make sure that it is
   1593   // not one of the global object types.
   1594   HValue* map =
   1595       Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
   1596   HValue* instance_type =
   1597       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
   1598   HValue* global_type = Add<HConstant>(JS_GLOBAL_OBJECT_TYPE);
   1599 
   1600   IfBuilder if_global_object(this);
   1601   if_global_object.If<HCompareNumericAndBranch>(instance_type, global_type,
   1602                                                 Token::EQ);
   1603   if_global_object.ThenDeopt(Deoptimizer::kReceiverWasAGlobalObject);
   1604   if_global_object.End();
   1605 }
   1606 
   1607 
   1608 void HGraphBuilder::BuildTestForDictionaryProperties(
   1609     HValue* object,
   1610     HIfContinuation* continuation) {
   1611   HValue* properties = Add<HLoadNamedField>(
   1612       object, nullptr, HObjectAccess::ForPropertiesPointer());
   1613   HValue* properties_map =
   1614       Add<HLoadNamedField>(properties, nullptr, HObjectAccess::ForMap());
   1615   HValue* hash_map = Add<HLoadRoot>(Heap::kHashTableMapRootIndex);
   1616   IfBuilder builder(this);
   1617   builder.If<HCompareObjectEqAndBranch>(properties_map, hash_map);
   1618   builder.CaptureContinuation(continuation);
   1619 }
   1620 
   1621 
   1622 HValue* HGraphBuilder::BuildKeyedLookupCacheHash(HValue* object,
   1623                                                  HValue* key) {
   1624   // Load the map of the receiver, compute the keyed lookup cache hash
   1625   // based on 32 bits of the map pointer and the string hash.
   1626   HValue* object_map =
   1627       Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMapAsInteger32());
   1628   HValue* shifted_map = AddUncasted<HShr>(
   1629       object_map, Add<HConstant>(KeyedLookupCache::kMapHashShift));
   1630   HValue* string_hash =
   1631       Add<HLoadNamedField>(key, nullptr, HObjectAccess::ForStringHashField());
   1632   HValue* shifted_hash = AddUncasted<HShr>(
   1633       string_hash, Add<HConstant>(String::kHashShift));
   1634   HValue* xor_result = AddUncasted<HBitwise>(Token::BIT_XOR, shifted_map,
   1635                                              shifted_hash);
   1636   int mask = (KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask);
   1637   return AddUncasted<HBitwise>(Token::BIT_AND, xor_result,
   1638                                Add<HConstant>(mask));
   1639 }
   1640 
   1641 
   1642 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
   1643   int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
   1644   HValue* seed = Add<HConstant>(seed_value);
   1645   HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);
   1646 
   1647   // hash = ~hash + (hash << 15);
   1648   HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
   1649   HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
   1650                                            graph()->GetConstantMinus1());
   1651   hash = AddUncasted<HAdd>(shifted_hash, not_hash);
   1652 
   1653   // hash = hash ^ (hash >> 12);
   1654   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
   1655   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1656 
   1657   // hash = hash + (hash << 2);
   1658   shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
   1659   hash = AddUncasted<HAdd>(hash, shifted_hash);
   1660 
   1661   // hash = hash ^ (hash >> 4);
   1662   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
   1663   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1664 
   1665   // hash = hash * 2057;
   1666   hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
   1667   hash->ClearFlag(HValue::kCanOverflow);
   1668 
   1669   // hash = hash ^ (hash >> 16);
   1670   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
   1671   return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1672 }
   1673 
   1674 
   1675 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(
   1676     HValue* receiver, HValue* elements, HValue* key, HValue* hash,
   1677     LanguageMode language_mode) {
   1678   HValue* capacity =
   1679       Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
   1680                       nullptr, nullptr, FAST_ELEMENTS);
   1681 
   1682   HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
   1683   mask->ChangeRepresentation(Representation::Integer32());
   1684   mask->ClearFlag(HValue::kCanOverflow);
   1685 
   1686   HValue* entry = hash;
   1687   HValue* count = graph()->GetConstant1();
   1688   Push(entry);
   1689   Push(count);
   1690 
   1691   HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
   1692                                               graph()->CreateBasicBlock());
   1693   HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
   1694                                                graph()->CreateBasicBlock());
   1695   LoopBuilder probe_loop(this);
   1696   probe_loop.BeginBody(2);  // Drop entry, count from last environment to
   1697                             // appease live range building without simulates.
   1698 
   1699   count = Pop();
   1700   entry = Pop();
   1701   entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
   1702   int entry_size = SeededNumberDictionary::kEntrySize;
   1703   HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size));
   1704   base_index->ClearFlag(HValue::kCanOverflow);
   1705   int start_offset = SeededNumberDictionary::kElementsStartIndex;
   1706   HValue* key_index =
   1707       AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
   1708   key_index->ClearFlag(HValue::kCanOverflow);
   1709 
   1710   HValue* candidate_key =
   1711       Add<HLoadKeyed>(elements, key_index, nullptr, nullptr, FAST_ELEMENTS);
   1712   IfBuilder if_undefined(this);
   1713   if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
   1714                                              graph()->GetConstantUndefined());
   1715   if_undefined.Then();
   1716   {
   1717     // element == undefined means "not found". Call the runtime.
   1718     // TODO(jkummerow): walk the prototype chain instead.
   1719     Add<HPushArguments>(receiver, key);
   1720     Push(Add<HCallRuntime>(
   1721         Runtime::FunctionForId(is_strong(language_mode)
   1722                                    ? Runtime::kKeyedGetPropertyStrong
   1723                                    : Runtime::kKeyedGetProperty),
   1724         2));
   1725   }
   1726   if_undefined.Else();
   1727   {
   1728     IfBuilder if_match(this);
   1729     if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
   1730     if_match.Then();
   1731     if_match.Else();
   1732 
   1733     // Update non-internalized string in the dictionary with internalized key?
   1734     IfBuilder if_update_with_internalized(this);
   1735     HValue* smi_check =
   1736         if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
   1737     if_update_with_internalized.And();
   1738     HValue* map = AddLoadMap(candidate_key, smi_check);
   1739     HValue* instance_type =
   1740         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
   1741     HValue* not_internalized_bit = AddUncasted<HBitwise>(
   1742         Token::BIT_AND, instance_type,
   1743         Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
   1744     if_update_with_internalized.If<HCompareNumericAndBranch>(
   1745         not_internalized_bit, graph()->GetConstant0(), Token::NE);
   1746     if_update_with_internalized.And();
   1747     if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
   1748         candidate_key, graph()->GetConstantHole());
   1749     if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
   1750                                                                key, Token::EQ);
   1751     if_update_with_internalized.Then();
   1752     // Replace a key that is a non-internalized string by the equivalent
   1753     // internalized string for faster further lookups.
   1754     Add<HStoreKeyed>(elements, key_index, key, nullptr, FAST_ELEMENTS);
   1755     if_update_with_internalized.Else();
   1756 
   1757     if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
   1758     if_match.JoinContinuation(&found_key_match_continuation);
   1759 
   1760     IfBuilder found_key_match(this, &found_key_match_continuation);
   1761     found_key_match.Then();
   1762     // Key at current probe matches. Relevant bits in the |details| field must
   1763     // be zero, otherwise the dictionary element requires special handling.
   1764     HValue* details_index =
   1765         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
   1766     details_index->ClearFlag(HValue::kCanOverflow);
   1767     HValue* details = Add<HLoadKeyed>(elements, details_index, nullptr, nullptr,
   1768                                       FAST_ELEMENTS);
   1769     int details_mask = PropertyDetails::TypeField::kMask;
   1770     details = AddUncasted<HBitwise>(Token::BIT_AND, details,
   1771                                     Add<HConstant>(details_mask));
   1772     IfBuilder details_compare(this);
   1773     details_compare.If<HCompareNumericAndBranch>(
   1774         details, graph()->GetConstant0(), Token::EQ);
   1775     details_compare.Then();
   1776     HValue* result_index =
   1777         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
   1778     result_index->ClearFlag(HValue::kCanOverflow);
   1779     Push(Add<HLoadKeyed>(elements, result_index, nullptr, nullptr,
   1780                          FAST_ELEMENTS));
   1781     details_compare.Else();
   1782     Add<HPushArguments>(receiver, key);
   1783     Push(Add<HCallRuntime>(
   1784         Runtime::FunctionForId(is_strong(language_mode)
   1785                                    ? Runtime::kKeyedGetPropertyStrong
   1786                                    : Runtime::kKeyedGetProperty),
   1787         2));
   1788     details_compare.End();
   1789 
   1790     found_key_match.Else();
   1791     found_key_match.JoinContinuation(&return_or_loop_continuation);
   1792   }
   1793   if_undefined.JoinContinuation(&return_or_loop_continuation);
   1794 
   1795   IfBuilder return_or_loop(this, &return_or_loop_continuation);
   1796   return_or_loop.Then();
   1797   probe_loop.Break();
   1798 
   1799   return_or_loop.Else();
   1800   entry = AddUncasted<HAdd>(entry, count);
   1801   entry->ClearFlag(HValue::kCanOverflow);
   1802   count = AddUncasted<HAdd>(count, graph()->GetConstant1());
   1803   count->ClearFlag(HValue::kCanOverflow);
   1804   Push(entry);
   1805   Push(count);
   1806 
   1807   probe_loop.EndBody();
   1808 
   1809   return_or_loop.End();
   1810 
   1811   return Pop();
   1812 }
   1813 
   1814 
   1815 HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value,
   1816                                                    HValue* done) {
   1817   NoObservableSideEffectsScope scope(this);
   1818 
   1819   // Allocate the JSIteratorResult object.
   1820   HValue* result =
   1821       Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(),
   1822                      NOT_TENURED, JS_ITERATOR_RESULT_TYPE);
   1823 
   1824   // Initialize the JSIteratorResult object.
   1825   HValue* native_context = BuildGetNativeContext();
   1826   HValue* map = Add<HLoadNamedField>(
   1827       native_context, nullptr,
   1828       HObjectAccess::ForContextSlot(Context::ITERATOR_RESULT_MAP_INDEX));
   1829   Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
   1830   HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
   1831   Add<HStoreNamedField>(result, HObjectAccess::ForPropertiesPointer(),
   1832                         empty_fixed_array);
   1833   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(),
   1834                         empty_fixed_array);
   1835   Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
   1836                                     JSIteratorResult::kValueOffset),
   1837                         value);
   1838   Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
   1839                                     JSIteratorResult::kDoneOffset),
   1840                         done);
   1841   STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
   1842   return result;
   1843 }
   1844 
   1845 
   1846 HValue* HGraphBuilder::BuildRegExpConstructResult(HValue* length,
   1847                                                   HValue* index,
   1848                                                   HValue* input) {
   1849   NoObservableSideEffectsScope scope(this);
   1850   HConstant* max_length = Add<HConstant>(JSArray::kInitialMaxFastElementArray);
   1851   Add<HBoundsCheck>(length, max_length);
   1852 
   1853   // Generate size calculation code here in order to make it dominate
   1854   // the JSRegExpResult allocation.
   1855   ElementsKind elements_kind = FAST_ELEMENTS;
   1856   HValue* size = BuildCalculateElementsSize(elements_kind, length);
   1857 
   1858   // Allocate the JSRegExpResult and the FixedArray in one step.
   1859   HValue* result = Add<HAllocate>(
   1860       Add<HConstant>(JSRegExpResult::kSize), HType::JSArray(),
   1861       NOT_TENURED, JS_ARRAY_TYPE);
   1862 
   1863   // Initialize the JSRegExpResult header.
   1864   HValue* native_context = Add<HLoadNamedField>(
   1865       context(), nullptr,
   1866       HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
   1867   Add<HStoreNamedField>(
   1868       result, HObjectAccess::ForMap(),
   1869       Add<HLoadNamedField>(
   1870           native_context, nullptr,
   1871           HObjectAccess::ForContextSlot(Context::REGEXP_RESULT_MAP_INDEX)));
   1872   HConstant* empty_fixed_array =
   1873       Add<HConstant>(isolate()->factory()->empty_fixed_array());
   1874   Add<HStoreNamedField>(
   1875       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
   1876       empty_fixed_array);
   1877   Add<HStoreNamedField>(
   1878       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
   1879       empty_fixed_array);
   1880   Add<HStoreNamedField>(
   1881       result, HObjectAccess::ForJSArrayOffset(JSArray::kLengthOffset), length);
   1882 
   1883   // Initialize the additional fields.
   1884   Add<HStoreNamedField>(
   1885       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kIndexOffset),
   1886       index);
   1887   Add<HStoreNamedField>(
   1888       result, HObjectAccess::ForJSArrayOffset(JSRegExpResult::kInputOffset),
   1889       input);
   1890 
   1891   // Allocate and initialize the elements header.
   1892   HAllocate* elements = BuildAllocateElements(elements_kind, size);
   1893   BuildInitializeElementsHeader(elements, elements_kind, length);
   1894 
   1895   if (!elements->has_size_upper_bound()) {
   1896     HConstant* size_in_bytes_upper_bound = EstablishElementsAllocationSize(
   1897         elements_kind, max_length->Integer32Value());
   1898     elements->set_size_upper_bound(size_in_bytes_upper_bound);
   1899   }
   1900 
   1901   Add<HStoreNamedField>(
   1902       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
   1903       elements);
   1904 
   1905   // Initialize the elements contents with undefined.
   1906   BuildFillElementsWithValue(
   1907       elements, elements_kind, graph()->GetConstant0(), length,
   1908       graph()->GetConstantUndefined());
   1909 
   1910   return result;
   1911 }
   1912 
   1913 
   1914 HValue* HGraphBuilder::BuildNumberToString(HValue* object, Type* type) {
   1915   NoObservableSideEffectsScope scope(this);
   1916 
   1917   // Convert constant numbers at compile time.
   1918   if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
   1919     Handle<Object> number = HConstant::cast(object)->handle(isolate());
   1920     Handle<String> result = isolate()->factory()->NumberToString(number);
   1921     return Add<HConstant>(result);
   1922   }
   1923 
   1924   // Create a joinable continuation.
   1925   HIfContinuation found(graph()->CreateBasicBlock(),
   1926                         graph()->CreateBasicBlock());
   1927 
   1928   // Load the number string cache.
   1929   HValue* number_string_cache =
   1930       Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
   1931 
   1932   // Make the hash mask from the length of the number string cache. It
   1933   // contains two elements (number and string) for each cache entry.
   1934   HValue* mask = AddLoadFixedArrayLength(number_string_cache);
   1935   mask->set_type(HType::Smi());
   1936   mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
   1937   mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
   1938 
   1939   // Check whether object is a smi.
   1940   IfBuilder if_objectissmi(this);
   1941   if_objectissmi.If<HIsSmiAndBranch>(object);
   1942   if_objectissmi.Then();
   1943   {
   1944     // Compute hash for smi similar to smi_get_hash().
   1945     HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);
   1946 
   1947     // Load the key.
   1948     HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
   1949     HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
   1950                                   nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE);
   1951 
   1952     // Check if object == key.
   1953     IfBuilder if_objectiskey(this);
   1954     if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
   1955     if_objectiskey.Then();
   1956     {
   1957       // Make the key_index available.
   1958       Push(key_index);
   1959     }
   1960     if_objectiskey.JoinContinuation(&found);
   1961   }
   1962   if_objectissmi.Else();
   1963   {
   1964     if (type->Is(Type::SignedSmall())) {
   1965       if_objectissmi.Deopt(Deoptimizer::kExpectedSmi);
   1966     } else {
   1967       // Check if the object is a heap number.
   1968       IfBuilder if_objectisnumber(this);
   1969       HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
   1970           object, isolate()->factory()->heap_number_map());
   1971       if_objectisnumber.Then();
   1972       {
   1973         // Compute hash for heap number similar to double_get_hash().
   1974         HValue* low = Add<HLoadNamedField>(
   1975             object, objectisnumber,
   1976             HObjectAccess::ForHeapNumberValueLowestBits());
   1977         HValue* high = Add<HLoadNamedField>(
   1978             object, objectisnumber,
   1979             HObjectAccess::ForHeapNumberValueHighestBits());
   1980         HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
   1981         hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
   1982 
   1983         // Load the key.
   1984         HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
   1985         HValue* key =
   1986             Add<HLoadKeyed>(number_string_cache, key_index, nullptr, nullptr,
   1987                             FAST_ELEMENTS, ALLOW_RETURN_HOLE);
   1988 
   1989         // Check if the key is a heap number and compare it with the object.
   1990         IfBuilder if_keyisnotsmi(this);
   1991         HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
   1992         if_keyisnotsmi.Then();
   1993         {
   1994           IfBuilder if_keyisheapnumber(this);
   1995           if_keyisheapnumber.If<HCompareMap>(
   1996               key, isolate()->factory()->heap_number_map());
   1997           if_keyisheapnumber.Then();
   1998           {
   1999             // Check if values of key and object match.
   2000             IfBuilder if_keyeqobject(this);
   2001             if_keyeqobject.If<HCompareNumericAndBranch>(
   2002                 Add<HLoadNamedField>(key, keyisnotsmi,
   2003                                      HObjectAccess::ForHeapNumberValue()),
   2004                 Add<HLoadNamedField>(object, objectisnumber,
   2005                                      HObjectAccess::ForHeapNumberValue()),
   2006                 Token::EQ);
   2007             if_keyeqobject.Then();
   2008             {
   2009               // Make the key_index available.
   2010               Push(key_index);
   2011             }
   2012             if_keyeqobject.JoinContinuation(&found);
   2013           }
   2014           if_keyisheapnumber.JoinContinuation(&found);
   2015         }
   2016         if_keyisnotsmi.JoinContinuation(&found);
   2017       }
   2018       if_objectisnumber.Else();
   2019       {
   2020         if (type->Is(Type::Number())) {
   2021           if_objectisnumber.Deopt(Deoptimizer::kExpectedHeapNumber);
   2022         }
   2023       }
   2024       if_objectisnumber.JoinContinuation(&found);
   2025     }
   2026   }
   2027   if_objectissmi.JoinContinuation(&found);
   2028 
   2029   // Check for cache hit.
   2030   IfBuilder if_found(this, &found);
   2031   if_found.Then();
   2032   {
   2033     // Count number to string operation in native code.
   2034     AddIncrementCounter(isolate()->counters()->number_to_string_native());
   2035 
   2036     // Load the value in case of cache hit.
   2037     HValue* key_index = Pop();
   2038     HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
   2039     Push(Add<HLoadKeyed>(number_string_cache, value_index, nullptr, nullptr,
   2040                          FAST_ELEMENTS, ALLOW_RETURN_HOLE));
   2041   }
   2042   if_found.Else();
   2043   {
   2044     // Cache miss, fallback to runtime.
   2045     Add<HPushArguments>(object);
   2046     Push(Add<HCallRuntime>(
   2047             Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
   2048             1));
   2049   }
   2050   if_found.End();
   2051 
   2052   return Pop();
   2053 }
   2054 
   2055 
   2056 HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
   2057   NoObservableSideEffectsScope scope(this);
   2058 
   2059   // Create a joinable continuation.
   2060   HIfContinuation wrap(graph()->CreateBasicBlock(),
   2061                        graph()->CreateBasicBlock());
   2062 
   2063   // Determine the proper global constructor function required to wrap
   2064   // {receiver} into a JSValue, unless {receiver} is already a {JSReceiver}, in
   2065   // which case we just return it.  Deopts to Runtime::kToObject if {receiver}
   2066   // is undefined or null.
   2067   IfBuilder receiver_is_smi(this);
   2068   receiver_is_smi.If<HIsSmiAndBranch>(receiver);
   2069   receiver_is_smi.Then();
   2070   {
   2071     // Use global Number function.
   2072     Push(Add<HConstant>(Context::NUMBER_FUNCTION_INDEX));
   2073   }
   2074   receiver_is_smi.Else();
   2075   {
   2076     // Determine {receiver} map and instance type.
   2077     HValue* receiver_map =
   2078         Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
   2079     HValue* receiver_instance_type = Add<HLoadNamedField>(
   2080         receiver_map, nullptr, HObjectAccess::ForMapInstanceType());
   2081 
   2082     // First check whether {receiver} is already a spec object (fast case).
   2083     IfBuilder receiver_is_not_spec_object(this);
   2084     receiver_is_not_spec_object.If<HCompareNumericAndBranch>(
   2085         receiver_instance_type, Add<HConstant>(FIRST_JS_RECEIVER_TYPE),
   2086         Token::LT);
   2087     receiver_is_not_spec_object.Then();
   2088     {
   2089       // Load the constructor function index from the {receiver} map.
   2090       HValue* constructor_function_index = Add<HLoadNamedField>(
   2091           receiver_map, nullptr,
   2092           HObjectAccess::ForMapInObjectPropertiesOrConstructorFunctionIndex());
   2093 
   2094       // Check if {receiver} has a constructor (null and undefined have no
   2095       // constructors, so we deoptimize to the runtime to throw an exception).
   2096       IfBuilder constructor_function_index_is_invalid(this);
   2097       constructor_function_index_is_invalid.If<HCompareNumericAndBranch>(
   2098           constructor_function_index,
   2099           Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ);
   2100       constructor_function_index_is_invalid.ThenDeopt(
   2101           Deoptimizer::kUndefinedOrNullInToObject);
   2102       constructor_function_index_is_invalid.End();
   2103 
   2104       // Use the global constructor function.
   2105       Push(constructor_function_index);
   2106     }
   2107     receiver_is_not_spec_object.JoinContinuation(&wrap);
   2108   }
   2109   receiver_is_smi.JoinContinuation(&wrap);
   2110 
   2111   // Wrap the receiver if necessary.
   2112   IfBuilder if_wrap(this, &wrap);
   2113   if_wrap.Then();
   2114   {
   2115     // Grab the constructor function index.
   2116     HValue* constructor_index = Pop();
   2117 
   2118     // Load native context.
   2119     HValue* native_context = BuildGetNativeContext();
   2120 
   2121     // Determine the initial map for the global constructor.
   2122     HValue* constructor = Add<HLoadKeyed>(native_context, constructor_index,
   2123                                           nullptr, nullptr, FAST_ELEMENTS);
   2124     HValue* constructor_initial_map = Add<HLoadNamedField>(
   2125         constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
   2126     // Allocate and initialize a JSValue wrapper.
   2127     HValue* value =
   2128         BuildAllocate(Add<HConstant>(JSValue::kSize), HType::JSObject(),
   2129                       JS_VALUE_TYPE, HAllocationMode());
   2130     Add<HStoreNamedField>(value, HObjectAccess::ForMap(),
   2131                           constructor_initial_map);
   2132     HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
   2133     Add<HStoreNamedField>(value, HObjectAccess::ForPropertiesPointer(),
   2134                           empty_fixed_array);
   2135     Add<HStoreNamedField>(value, HObjectAccess::ForElementsPointer(),
   2136                           empty_fixed_array);
   2137     Add<HStoreNamedField>(value, HObjectAccess::ForObservableJSObjectOffset(
   2138                                      JSValue::kValueOffset),
   2139                           receiver);
   2140     Push(value);
   2141   }
   2142   if_wrap.Else();
   2143   { Push(receiver); }
   2144   if_wrap.End();
   2145   return Pop();
   2146 }
   2147 
   2148 
   2149 HAllocate* HGraphBuilder::BuildAllocate(
   2150     HValue* object_size,
   2151     HType type,
   2152     InstanceType instance_type,
   2153     HAllocationMode allocation_mode) {
   2154   // Compute the effective allocation size.
   2155   HValue* size = object_size;
   2156   if (allocation_mode.CreateAllocationMementos()) {
   2157     size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
   2158     size->ClearFlag(HValue::kCanOverflow);
   2159   }
   2160 
   2161   // Perform the actual allocation.
   2162   HAllocate* object = Add<HAllocate>(
   2163       size, type, allocation_mode.GetPretenureMode(),
   2164       instance_type, allocation_mode.feedback_site());
   2165 
   2166   // Setup the allocation memento.
   2167   if (allocation_mode.CreateAllocationMementos()) {
   2168     BuildCreateAllocationMemento(
   2169         object, object_size, allocation_mode.current_site());
   2170   }
   2171 
   2172   return object;
   2173 }
   2174 
   2175 
   2176 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
   2177                                              HValue* right_length) {
   2178   // Compute the combined string length and check against max string length.
   2179   HValue* length = AddUncasted<HAdd>(left_length, right_length);
   2180   // Check that length <= kMaxLength <=> length < MaxLength + 1.
   2181   HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
   2182   Add<HBoundsCheck>(length, max_length);
   2183   return length;
   2184 }
   2185 
   2186 
   2187 HValue* HGraphBuilder::BuildCreateConsString(
   2188     HValue* length,
   2189     HValue* left,
   2190     HValue* right,
   2191     HAllocationMode allocation_mode) {
   2192   // Determine the string instance types.
   2193   HInstruction* left_instance_type = AddLoadStringInstanceType(left);
   2194   HInstruction* right_instance_type = AddLoadStringInstanceType(right);
   2195 
   2196   // Allocate the cons string object. HAllocate does not care whether we
   2197   // pass CONS_STRING_TYPE or CONS_ONE_BYTE_STRING_TYPE here, so we just use
   2198   // CONS_STRING_TYPE here. Below we decide whether the cons string is
   2199   // one-byte or two-byte and set the appropriate map.
   2200   DCHECK(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
   2201                                             CONS_ONE_BYTE_STRING_TYPE));
   2202   HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
   2203                                     HType::String(), CONS_STRING_TYPE,
   2204                                     allocation_mode);
   2205 
   2206   // Compute intersection and difference of instance types.
   2207   HValue* anded_instance_types = AddUncasted<HBitwise>(
   2208       Token::BIT_AND, left_instance_type, right_instance_type);
   2209   HValue* xored_instance_types = AddUncasted<HBitwise>(
   2210       Token::BIT_XOR, left_instance_type, right_instance_type);
   2211 
   2212   // We create a one-byte cons string if
   2213   // 1. both strings are one-byte, or
   2214   // 2. at least one of the strings is two-byte, but happens to contain only
   2215   //    one-byte characters.
   2216   // To do this, we check
   2217   // 1. if both strings are one-byte, or if the one-byte data hint is set in
   2218   //    both strings, or
   2219   // 2. if one of the strings has the one-byte data hint set and the other
   2220   //    string is one-byte.
   2221   IfBuilder if_onebyte(this);
   2222   STATIC_ASSERT(kOneByteStringTag != 0);
   2223   STATIC_ASSERT(kOneByteDataHintMask != 0);
   2224   if_onebyte.If<HCompareNumericAndBranch>(
   2225       AddUncasted<HBitwise>(
   2226           Token::BIT_AND, anded_instance_types,
   2227           Add<HConstant>(static_cast<int32_t>(
   2228                   kStringEncodingMask | kOneByteDataHintMask))),
   2229       graph()->GetConstant0(), Token::NE);
   2230   if_onebyte.Or();
   2231   STATIC_ASSERT(kOneByteStringTag != 0 &&
   2232                 kOneByteDataHintTag != 0 &&
   2233                 kOneByteDataHintTag != kOneByteStringTag);
   2234   if_onebyte.If<HCompareNumericAndBranch>(
   2235       AddUncasted<HBitwise>(
   2236           Token::BIT_AND, xored_instance_types,
   2237           Add<HConstant>(static_cast<int32_t>(
   2238                   kOneByteStringTag | kOneByteDataHintTag))),
   2239       Add<HConstant>(static_cast<int32_t>(
   2240               kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
   2241   if_onebyte.Then();
   2242   {
   2243     // We can safely skip the write barrier for storing the map here.
   2244     Add<HStoreNamedField>(
   2245         result, HObjectAccess::ForMap(),
   2246         Add<HConstant>(isolate()->factory()->cons_one_byte_string_map()));
   2247   }
   2248   if_onebyte.Else();
   2249   {
   2250     // We can safely skip the write barrier for storing the map here.
   2251     Add<HStoreNamedField>(
   2252         result, HObjectAccess::ForMap(),
   2253         Add<HConstant>(isolate()->factory()->cons_string_map()));
   2254   }
   2255   if_onebyte.End();
   2256 
   2257   // Initialize the cons string fields.
   2258   Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
   2259                         Add<HConstant>(String::kEmptyHashField));
   2260   Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
   2261   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
   2262   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
   2263 
   2264   // Count the native string addition.
   2265   AddIncrementCounter(isolate()->counters()->string_add_native());
   2266 
   2267   return result;
   2268 }
   2269 
   2270 
   2271 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
   2272                                             HValue* src_offset,
   2273                                             String::Encoding src_encoding,
   2274                                             HValue* dst,
   2275                                             HValue* dst_offset,
   2276                                             String::Encoding dst_encoding,
   2277                                             HValue* length) {
   2278   DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
   2279          src_encoding == String::ONE_BYTE_ENCODING);
   2280   LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
   2281   HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
   2282   {
   2283     HValue* src_index = AddUncasted<HAdd>(src_offset, index);
   2284     HValue* value =
   2285         AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
   2286     HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
   2287     Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
   2288   }
   2289   loop.EndBody();
   2290 }
   2291 
   2292 
   2293 HValue* HGraphBuilder::BuildObjectSizeAlignment(
   2294     HValue* unaligned_size, int header_size) {
   2295   DCHECK((header_size & kObjectAlignmentMask) == 0);
   2296   HValue* size = AddUncasted<HAdd>(
   2297       unaligned_size, Add<HConstant>(static_cast<int32_t>(
   2298           header_size + kObjectAlignmentMask)));
   2299   size->ClearFlag(HValue::kCanOverflow);
   2300   return AddUncasted<HBitwise>(
   2301       Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
   2302           ~kObjectAlignmentMask)));
   2303 }
   2304 
   2305 
   2306 HValue* HGraphBuilder::BuildUncheckedStringAdd(
   2307     HValue* left,
   2308     HValue* right,
   2309     HAllocationMode allocation_mode) {
   2310   // Determine the string lengths.
   2311   HValue* left_length = AddLoadStringLength(left);
   2312   HValue* right_length = AddLoadStringLength(right);
   2313 
   2314   // Compute the combined string length.
   2315   HValue* length = BuildAddStringLengths(left_length, right_length);
   2316 
   2317   // Do some manual constant folding here.
   2318   if (left_length->IsConstant()) {
   2319     HConstant* c_left_length = HConstant::cast(left_length);
   2320     DCHECK_NE(0, c_left_length->Integer32Value());
   2321     if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
   2322       // The right string contains at least one character.
   2323       return BuildCreateConsString(length, left, right, allocation_mode);
   2324     }
   2325   } else if (right_length->IsConstant()) {
   2326     HConstant* c_right_length = HConstant::cast(right_length);
   2327     DCHECK_NE(0, c_right_length->Integer32Value());
   2328     if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
   2329       // The left string contains at least one character.
   2330       return BuildCreateConsString(length, left, right, allocation_mode);
   2331     }
   2332   }
   2333 
   2334   // Check if we should create a cons string.
   2335   IfBuilder if_createcons(this);
   2336   if_createcons.If<HCompareNumericAndBranch>(
   2337       length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
   2338   if_createcons.Then();
   2339   {
   2340     // Create a cons string.
   2341     Push(BuildCreateConsString(length, left, right, allocation_mode));
   2342   }
   2343   if_createcons.Else();
   2344   {
   2345     // Determine the string instance types.
   2346     HValue* left_instance_type = AddLoadStringInstanceType(left);
   2347     HValue* right_instance_type = AddLoadStringInstanceType(right);
   2348 
   2349     // Compute union and difference of instance types.
   2350     HValue* ored_instance_types = AddUncasted<HBitwise>(
   2351         Token::BIT_OR, left_instance_type, right_instance_type);
   2352     HValue* xored_instance_types = AddUncasted<HBitwise>(
   2353         Token::BIT_XOR, left_instance_type, right_instance_type);
   2354 
   2355     // Check if both strings have the same encoding and both are
   2356     // sequential.
   2357     IfBuilder if_sameencodingandsequential(this);
   2358     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
   2359         AddUncasted<HBitwise>(
   2360             Token::BIT_AND, xored_instance_types,
   2361             Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
   2362         graph()->GetConstant0(), Token::EQ);
   2363     if_sameencodingandsequential.And();
   2364     STATIC_ASSERT(kSeqStringTag == 0);
   2365     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
   2366         AddUncasted<HBitwise>(
   2367             Token::BIT_AND, ored_instance_types,
   2368             Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
   2369         graph()->GetConstant0(), Token::EQ);
   2370     if_sameencodingandsequential.Then();
   2371     {
   2372       HConstant* string_map =
   2373           Add<HConstant>(isolate()->factory()->string_map());
   2374       HConstant* one_byte_string_map =
   2375           Add<HConstant>(isolate()->factory()->one_byte_string_map());
   2376 
   2377       // Determine map and size depending on whether result is one-byte string.
   2378       IfBuilder if_onebyte(this);
   2379       STATIC_ASSERT(kOneByteStringTag != 0);
   2380       if_onebyte.If<HCompareNumericAndBranch>(
   2381           AddUncasted<HBitwise>(
   2382               Token::BIT_AND, ored_instance_types,
   2383               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
   2384           graph()->GetConstant0(), Token::NE);
   2385       if_onebyte.Then();
   2386       {
   2387         // Allocate sequential one-byte string object.
   2388         Push(length);
   2389         Push(one_byte_string_map);
   2390       }
   2391       if_onebyte.Else();
   2392       {
   2393         // Allocate sequential two-byte string object.
   2394         HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
   2395         size->ClearFlag(HValue::kCanOverflow);
   2396         size->SetFlag(HValue::kUint32);
   2397         Push(size);
   2398         Push(string_map);
   2399       }
   2400       if_onebyte.End();
   2401       HValue* map = Pop();
   2402 
   2403       // Calculate the number of bytes needed for the characters in the
   2404       // string while observing object alignment.
   2405       STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
   2406       HValue* size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);
   2407 
   2408       IfBuilder if_size(this);
   2409       if_size.If<HCompareNumericAndBranch>(
   2410           size, Add<HConstant>(Page::kMaxRegularHeapObjectSize), Token::LT);
   2411       if_size.Then();
   2412       {
   2413         // Allocate the string object. HAllocate does not care whether we pass
   2414         // STRING_TYPE or ONE_BYTE_STRING_TYPE here, so we just use STRING_TYPE.
   2415         HAllocate* result =
   2416             BuildAllocate(size, HType::String(), STRING_TYPE, allocation_mode);
   2417         Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
   2418 
   2419         // Initialize the string fields.
   2420         Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
   2421                               Add<HConstant>(String::kEmptyHashField));
   2422         Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
   2423 
   2424         // Copy characters to the result string.
   2425         IfBuilder if_twobyte(this);
   2426         if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
   2427         if_twobyte.Then();
   2428         {
   2429           // Copy characters from the left string.
   2430           BuildCopySeqStringChars(
   2431               left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, result,
   2432               graph()->GetConstant0(), String::TWO_BYTE_ENCODING, left_length);
   2433 
   2434           // Copy characters from the right string.
   2435           BuildCopySeqStringChars(
   2436               right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, result,
   2437               left_length, String::TWO_BYTE_ENCODING, right_length);
   2438         }
   2439         if_twobyte.Else();
   2440         {
   2441           // Copy characters from the left string.
   2442           BuildCopySeqStringChars(
   2443               left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, result,
   2444               graph()->GetConstant0(), String::ONE_BYTE_ENCODING, left_length);
   2445 
   2446           // Copy characters from the right string.
   2447           BuildCopySeqStringChars(
   2448               right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, result,
   2449               left_length, String::ONE_BYTE_ENCODING, right_length);
   2450         }
   2451         if_twobyte.End();
   2452 
   2453         // Count the native string addition.
   2454         AddIncrementCounter(isolate()->counters()->string_add_native());
   2455 
   2456         // Return the sequential string.
   2457         Push(result);
   2458       }
   2459       if_size.Else();
   2460       {
   2461         // Fallback to the runtime to add the two strings. The string has to be
   2462         // allocated in LO space.
   2463         Add<HPushArguments>(left, right);
   2464         Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
   2465       }
   2466       if_size.End();
   2467     }
   2468     if_sameencodingandsequential.Else();
   2469     {
   2470       // Fallback to the runtime to add the two strings.
   2471       Add<HPushArguments>(left, right);
   2472       Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
   2473     }
   2474     if_sameencodingandsequential.End();
   2475   }
   2476   if_createcons.End();
   2477 
   2478   return Pop();
   2479 }
   2480 
   2481 
   2482 HValue* HGraphBuilder::BuildStringAdd(
   2483     HValue* left,
   2484     HValue* right,
   2485     HAllocationMode allocation_mode) {
   2486   NoObservableSideEffectsScope no_effects(this);
   2487 
   2488   // Determine string lengths.
   2489   HValue* left_length = AddLoadStringLength(left);
   2490   HValue* right_length = AddLoadStringLength(right);
   2491 
   2492   // Check if left string is empty.
   2493   IfBuilder if_leftempty(this);
   2494   if_leftempty.If<HCompareNumericAndBranch>(
   2495       left_length, graph()->GetConstant0(), Token::EQ);
   2496   if_leftempty.Then();
   2497   {
   2498     // Count the native string addition.
   2499     AddIncrementCounter(isolate()->counters()->string_add_native());
   2500 
   2501     // Just return the right string.
   2502     Push(right);
   2503   }
   2504   if_leftempty.Else();
   2505   {
   2506     // Check if right string is empty.
   2507     IfBuilder if_rightempty(this);
   2508     if_rightempty.If<HCompareNumericAndBranch>(
   2509         right_length, graph()->GetConstant0(), Token::EQ);
   2510     if_rightempty.Then();
   2511     {
   2512       // Count the native string addition.
   2513       AddIncrementCounter(isolate()->counters()->string_add_native());
   2514 
   2515       // Just return the left string.
   2516       Push(left);
   2517     }
   2518     if_rightempty.Else();
   2519     {
   2520       // Add the two non-empty strings.
   2521       Push(BuildUncheckedStringAdd(left, right, allocation_mode));
   2522     }
   2523     if_rightempty.End();
   2524   }
   2525   if_leftempty.End();
   2526 
   2527   return Pop();
   2528 }
   2529 
   2530 
   2531 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
   2532     HValue* checked_object,
   2533     HValue* key,
   2534     HValue* val,
   2535     bool is_js_array,
   2536     ElementsKind elements_kind,
   2537     PropertyAccessType access_type,
   2538     LoadKeyedHoleMode load_mode,
   2539     KeyedAccessStoreMode store_mode) {
   2540   DCHECK(top_info()->IsStub() || checked_object->IsCompareMap() ||
   2541          checked_object->IsCheckMaps());
   2542   DCHECK(!IsFixedTypedArrayElementsKind(elements_kind) || !is_js_array);
   2543   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
   2544   // on a HElementsTransition instruction. The flag can also be removed if the
   2545   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
   2546   // ElementsKind transitions. Finally, the dependency can be removed for stores
   2547   // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
   2548   // generated store code.
   2549   if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
   2550       (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
   2551     checked_object->ClearDependsOnFlag(kElementsKind);
   2552   }
   2553 
   2554   bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
   2555   bool fast_elements = IsFastObjectElementsKind(elements_kind);
   2556   HValue* elements = AddLoadElements(checked_object);
   2557   if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
   2558       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
   2559     HCheckMaps* check_cow_map = Add<HCheckMaps>(
   2560         elements, isolate()->factory()->fixed_array_map());
   2561     check_cow_map->ClearDependsOnFlag(kElementsKind);
   2562   }
   2563   HInstruction* length = NULL;
   2564   if (is_js_array) {
   2565     length = Add<HLoadNamedField>(
   2566         checked_object->ActualValue(), checked_object,
   2567         HObjectAccess::ForArrayLength(elements_kind));
   2568   } else {
   2569     length = AddLoadFixedArrayLength(elements);
   2570   }
   2571   length->set_type(HType::Smi());
   2572   HValue* checked_key = NULL;
   2573   if (IsFixedTypedArrayElementsKind(elements_kind)) {
   2574     checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
   2575 
   2576     HValue* external_pointer = Add<HLoadNamedField>(
   2577         elements, nullptr,
   2578         HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
   2579     HValue* base_pointer = Add<HLoadNamedField>(
   2580         elements, nullptr, HObjectAccess::ForFixedTypedArrayBaseBasePointer());
   2581     HValue* backing_store = AddUncasted<HAdd>(
   2582         external_pointer, base_pointer, Strength::WEAK, AddOfExternalAndTagged);
   2583 
   2584     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
   2585       NoObservableSideEffectsScope no_effects(this);
   2586       IfBuilder length_checker(this);
   2587       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
   2588       length_checker.Then();
   2589       IfBuilder negative_checker(this);
   2590       HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
   2591           key, graph()->GetConstant0(), Token::GTE);
   2592       negative_checker.Then();
   2593       HInstruction* result = AddElementAccess(
   2594           backing_store, key, val, bounds_check, checked_object->ActualValue(),
   2595           elements_kind, access_type);
   2596       negative_checker.ElseDeopt(Deoptimizer::kNegativeKeyEncountered);
   2597       negative_checker.End();
   2598       length_checker.End();
   2599       return result;
   2600     } else {
   2601       DCHECK(store_mode == STANDARD_STORE);
   2602       checked_key = Add<HBoundsCheck>(key, length);
   2603       return AddElementAccess(backing_store, checked_key, val, checked_object,
   2604                               checked_object->ActualValue(), elements_kind,
   2605                               access_type);
   2606     }
   2607   }
   2608   DCHECK(fast_smi_only_elements ||
   2609          fast_elements ||
   2610          IsFastDoubleElementsKind(elements_kind));
   2611 
   2612   // In case val is stored into a fast smi array, assure that the value is a smi
   2613   // before manipulating the backing store. Otherwise the actual store may
   2614   // deopt, leaving the backing store in an invalid state.
   2615   if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
   2616       !val->type().IsSmi()) {
   2617     val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
   2618   }
   2619 
   2620   if (IsGrowStoreMode(store_mode)) {
   2621     NoObservableSideEffectsScope no_effects(this);
   2622     Representation representation = HStoreKeyed::RequiredValueRepresentation(
   2623         elements_kind, STORE_TO_INITIALIZED_ENTRY);
   2624     val = AddUncasted<HForceRepresentation>(val, representation);
   2625     elements = BuildCheckForCapacityGrow(checked_object, elements,
   2626                                          elements_kind, length, key,
   2627                                          is_js_array, access_type);
   2628     checked_key = key;
   2629   } else {
   2630     checked_key = Add<HBoundsCheck>(key, length);
   2631 
   2632     if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
   2633       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
   2634         NoObservableSideEffectsScope no_effects(this);
   2635         elements = BuildCopyElementsOnWrite(checked_object, elements,
   2636                                             elements_kind, length);
   2637       } else {
   2638         HCheckMaps* check_cow_map = Add<HCheckMaps>(
   2639             elements, isolate()->factory()->fixed_array_map());
   2640         check_cow_map->ClearDependsOnFlag(kElementsKind);
   2641       }
   2642     }
   2643   }
   2644   return AddElementAccess(elements, checked_key, val, checked_object, nullptr,
   2645                           elements_kind, access_type, load_mode);
   2646 }
   2647 
   2648 
   2649 HValue* HGraphBuilder::BuildAllocateArrayFromLength(
   2650     JSArrayBuilder* array_builder,
   2651     HValue* length_argument) {
   2652   if (length_argument->IsConstant() &&
   2653       HConstant::cast(length_argument)->HasSmiValue()) {
   2654     int array_length = HConstant::cast(length_argument)->Integer32Value();
   2655     if (array_length == 0) {
   2656       return array_builder->AllocateEmptyArray();
   2657     } else {
   2658       return array_builder->AllocateArray(length_argument,
   2659                                           array_length,
   2660                                           length_argument);
   2661     }
   2662   }
   2663 
   2664   HValue* constant_zero = graph()->GetConstant0();
   2665   HConstant* max_alloc_length =
   2666       Add<HConstant>(JSArray::kInitialMaxFastElementArray);
   2667   HInstruction* checked_length = Add<HBoundsCheck>(length_argument,
   2668                                                    max_alloc_length);
   2669   IfBuilder if_builder(this);
   2670   if_builder.If<HCompareNumericAndBranch>(checked_length, constant_zero,
   2671                                           Token::EQ);
   2672   if_builder.Then();
   2673   const int initial_capacity = JSArray::kPreallocatedArrayElements;
   2674   HConstant* initial_capacity_node = Add<HConstant>(initial_capacity);
   2675   Push(initial_capacity_node);  // capacity
   2676   Push(constant_zero);          // length
   2677   if_builder.Else();
   2678   if (!(top_info()->IsStub()) &&
   2679       IsFastPackedElementsKind(array_builder->kind())) {
   2680     // We'll come back later with better (holey) feedback.
   2681     if_builder.Deopt(
   2682         Deoptimizer::kHoleyArrayDespitePackedElements_kindFeedback);
   2683   } else {
   2684     Push(checked_length);         // capacity
   2685     Push(checked_length);         // length
   2686   }
   2687   if_builder.End();
   2688 
   2689   // Figure out total size
   2690   HValue* length = Pop();
   2691   HValue* capacity = Pop();
   2692   return array_builder->AllocateArray(capacity, max_alloc_length, length);
   2693 }
   2694 
   2695 
   2696 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
   2697                                                   HValue* capacity) {
   2698   int elements_size = IsFastDoubleElementsKind(kind)
   2699       ? kDoubleSize
   2700       : kPointerSize;
   2701 
   2702   HConstant* elements_size_value = Add<HConstant>(elements_size);
   2703   HInstruction* mul =
   2704       HMul::NewImul(isolate(), zone(), context(), capacity->ActualValue(),
   2705                     elements_size_value);
   2706   AddInstruction(mul);
   2707   mul->ClearFlag(HValue::kCanOverflow);
   2708 
   2709   STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
   2710 
   2711   HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
   2712   HValue* total_size = AddUncasted<HAdd>(mul, header_size);
   2713   total_size->ClearFlag(HValue::kCanOverflow);
   2714   return total_size;
   2715 }
   2716 
   2717 
   2718 HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
   2719   int base_size = JSArray::kSize;
   2720   if (mode == TRACK_ALLOCATION_SITE) {
   2721     base_size += AllocationMemento::kSize;
   2722   }
   2723   HConstant* size_in_bytes = Add<HConstant>(base_size);
   2724   return Add<HAllocate>(
   2725       size_in_bytes, HType::JSArray(), NOT_TENURED, JS_OBJECT_TYPE);
   2726 }
   2727 
   2728 
   2729 HConstant* HGraphBuilder::EstablishElementsAllocationSize(
   2730     ElementsKind kind,
   2731     int capacity) {
   2732   int base_size = IsFastDoubleElementsKind(kind)
   2733       ? FixedDoubleArray::SizeFor(capacity)
   2734       : FixedArray::SizeFor(capacity);
   2735 
   2736   return Add<HConstant>(base_size);
   2737 }
   2738 
   2739 
   2740 HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
   2741                                                 HValue* size_in_bytes) {
   2742   InstanceType instance_type = IsFastDoubleElementsKind(kind)
   2743       ? FIXED_DOUBLE_ARRAY_TYPE
   2744       : FIXED_ARRAY_TYPE;
   2745 
   2746   return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
   2747                         instance_type);
   2748 }
   2749 
   2750 
   2751 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
   2752                                                   ElementsKind kind,
   2753                                                   HValue* capacity) {
   2754   Factory* factory = isolate()->factory();
   2755   Handle<Map> map = IsFastDoubleElementsKind(kind)
   2756       ? factory->fixed_double_array_map()
   2757       : factory->fixed_array_map();
   2758 
   2759   Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map));
   2760   Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
   2761                         capacity);
   2762 }
   2763 
   2764 
   2765 HValue* HGraphBuilder::BuildAllocateAndInitializeArray(ElementsKind kind,
   2766                                                        HValue* capacity) {
   2767   // The HForceRepresentation is to prevent possible deopt on int-smi
   2768   // conversion after allocation but before the new object fields are set.
   2769   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
   2770   HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
   2771   HValue* new_array = BuildAllocateElements(kind, size_in_bytes);
   2772   BuildInitializeElementsHeader(new_array, kind, capacity);
   2773   return new_array;
   2774 }
   2775 
   2776 
   2777 void HGraphBuilder::BuildJSArrayHeader(HValue* array,
   2778                                        HValue* array_map,
   2779                                        HValue* elements,
   2780                                        AllocationSiteMode mode,
   2781                                        ElementsKind elements_kind,
   2782                                        HValue* allocation_site_payload,
   2783                                        HValue* length_field) {
   2784   Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
   2785 
   2786   HConstant* empty_fixed_array =
   2787     Add<HConstant>(isolate()->factory()->empty_fixed_array());
   2788 
   2789   Add<HStoreNamedField>(
   2790       array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
   2791 
   2792   Add<HStoreNamedField>(
   2793       array, HObjectAccess::ForElementsPointer(),
   2794       elements != NULL ? elements : empty_fixed_array);
   2795 
   2796   Add<HStoreNamedField>(
   2797       array, HObjectAccess::ForArrayLength(elements_kind), length_field);
   2798 
   2799   if (mode == TRACK_ALLOCATION_SITE) {
   2800     BuildCreateAllocationMemento(
   2801         array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
   2802   }
   2803 }
   2804 
   2805 
   2806 HInstruction* HGraphBuilder::AddElementAccess(
   2807     HValue* elements, HValue* checked_key, HValue* val, HValue* dependency,
   2808     HValue* backing_store_owner, ElementsKind elements_kind,
   2809     PropertyAccessType access_type, LoadKeyedHoleMode load_mode) {
   2810   if (access_type == STORE) {
   2811     DCHECK(val != NULL);
   2812     if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
   2813       val = Add<HClampToUint8>(val);
   2814     }
   2815     return Add<HStoreKeyed>(elements, checked_key, val, backing_store_owner,
   2816                             elements_kind, STORE_TO_INITIALIZED_ENTRY);
   2817   }
   2818 
   2819   DCHECK(access_type == LOAD);
   2820   DCHECK(val == NULL);
   2821   HLoadKeyed* load =
   2822       Add<HLoadKeyed>(elements, checked_key, dependency, backing_store_owner,
   2823                       elements_kind, load_mode);
   2824   if (elements_kind == UINT32_ELEMENTS) {
   2825     graph()->RecordUint32Instruction(load);
   2826   }
   2827   return load;
   2828 }
   2829 
   2830 
   2831 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
   2832                                            HValue* dependency) {
   2833   return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
   2834 }
   2835 
   2836 
   2837 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
   2838                                                 HValue* dependency) {
   2839   return Add<HLoadNamedField>(
   2840       object, dependency, HObjectAccess::ForElementsPointer());
   2841 }
   2842 
   2843 
   2844 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
   2845     HValue* array,
   2846     HValue* dependency) {
   2847   return Add<HLoadNamedField>(
   2848       array, dependency, HObjectAccess::ForFixedArrayLength());
   2849 }
   2850 
   2851 
   2852 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array,
   2853                                                    ElementsKind kind,
   2854                                                    HValue* dependency) {
   2855   return Add<HLoadNamedField>(
   2856       array, dependency, HObjectAccess::ForArrayLength(kind));
   2857 }
   2858 
   2859 
   2860 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
   2861   HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
   2862                                                 graph_->GetConstant1());
   2863 
   2864   HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
   2865   new_capacity->ClearFlag(HValue::kCanOverflow);
   2866 
   2867   HValue* min_growth = Add<HConstant>(16);
   2868 
   2869   new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
   2870   new_capacity->ClearFlag(HValue::kCanOverflow);
   2871 
   2872   return new_capacity;
   2873 }
   2874 
   2875 
   2876 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
   2877                                                  HValue* elements,
   2878                                                  ElementsKind kind,
   2879                                                  ElementsKind new_kind,
   2880                                                  HValue* length,
   2881                                                  HValue* new_capacity) {
   2882   Add<HBoundsCheck>(new_capacity, Add<HConstant>(
   2883           (Page::kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
   2884           ElementsKindToShiftSize(new_kind)));
   2885 
   2886   HValue* new_elements =
   2887       BuildAllocateAndInitializeArray(new_kind, new_capacity);
   2888 
   2889   BuildCopyElements(elements, kind, new_elements,
   2890                     new_kind, length, new_capacity);
   2891 
   2892   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   2893                         new_elements);
   2894 
   2895   return new_elements;
   2896 }
   2897 
   2898 
   2899 void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
   2900                                                ElementsKind elements_kind,
   2901                                                HValue* from,
   2902                                                HValue* to,
   2903                                                HValue* value) {
   2904   if (to == NULL) {
   2905     to = AddLoadFixedArrayLength(elements);
   2906   }
   2907 
   2908   // Special loop unfolding case
   2909   STATIC_ASSERT(JSArray::kPreallocatedArrayElements <=
   2910                 kElementLoopUnrollThreshold);
   2911   int initial_capacity = -1;
   2912   if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
   2913     int constant_from = from->GetInteger32Constant();
   2914     int constant_to = to->GetInteger32Constant();
   2915 
   2916     if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
   2917       initial_capacity = constant_to;
   2918     }
   2919   }
   2920 
   2921   if (initial_capacity >= 0) {
   2922     for (int i = 0; i < initial_capacity; i++) {
   2923       HInstruction* key = Add<HConstant>(i);
   2924       Add<HStoreKeyed>(elements, key, value, nullptr, elements_kind);
   2925     }
   2926   } else {
   2927     // Carefully loop backwards so that the "from" remains live through the loop
   2928     // rather than the to. This often corresponds to keeping length live rather
   2929     // then capacity, which helps register allocation, since length is used more
   2930     // other than capacity after filling with holes.
   2931     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   2932 
   2933     HValue* key = builder.BeginBody(to, from, Token::GT);
   2934 
   2935     HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
   2936     adjusted_key->ClearFlag(HValue::kCanOverflow);
   2937 
   2938     Add<HStoreKeyed>(elements, adjusted_key, value, nullptr, elements_kind);
   2939 
   2940     builder.EndBody();
   2941   }
   2942 }
   2943 
   2944 
   2945 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
   2946                                               ElementsKind elements_kind,
   2947                                               HValue* from,
   2948                                               HValue* to) {
   2949   // Fast elements kinds need to be initialized in case statements below cause a
   2950   // garbage collection.
   2951 
   2952   HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
   2953                      ? graph()->GetConstantHole()
   2954                      : Add<HConstant>(HConstant::kHoleNaN);
   2955 
   2956   // Since we're about to store a hole value, the store instruction below must
   2957   // assume an elements kind that supports heap object values.
   2958   if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   2959     elements_kind = FAST_HOLEY_ELEMENTS;
   2960   }
   2961 
   2962   BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
   2963 }
   2964 
   2965 
   2966 void HGraphBuilder::BuildCopyProperties(HValue* from_properties,
   2967                                         HValue* to_properties, HValue* length,
   2968                                         HValue* capacity) {
   2969   ElementsKind kind = FAST_ELEMENTS;
   2970 
   2971   BuildFillElementsWithValue(to_properties, kind, length, capacity,
   2972                              graph()->GetConstantUndefined());
   2973 
   2974   LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   2975 
   2976   HValue* key = builder.BeginBody(length, graph()->GetConstant0(), Token::GT);
   2977 
   2978   key = AddUncasted<HSub>(key, graph()->GetConstant1());
   2979   key->ClearFlag(HValue::kCanOverflow);
   2980 
   2981   HValue* element =
   2982       Add<HLoadKeyed>(from_properties, key, nullptr, nullptr, kind);
   2983 
   2984   Add<HStoreKeyed>(to_properties, key, element, nullptr, kind);
   2985 
   2986   builder.EndBody();
   2987 }
   2988 
   2989 
   2990 void HGraphBuilder::BuildCopyElements(HValue* from_elements,
   2991                                       ElementsKind from_elements_kind,
   2992                                       HValue* to_elements,
   2993                                       ElementsKind to_elements_kind,
   2994                                       HValue* length,
   2995                                       HValue* capacity) {
   2996   int constant_capacity = -1;
   2997   if (capacity != NULL &&
   2998       capacity->IsConstant() &&
   2999       HConstant::cast(capacity)->HasInteger32Value()) {
   3000     int constant_candidate = HConstant::cast(capacity)->Integer32Value();
   3001     if (constant_candidate <= kElementLoopUnrollThreshold) {
   3002       constant_capacity = constant_candidate;
   3003     }
   3004   }
   3005 
   3006   bool pre_fill_with_holes =
   3007     IsFastDoubleElementsKind(from_elements_kind) &&
   3008     IsFastObjectElementsKind(to_elements_kind);
   3009   if (pre_fill_with_holes) {
   3010     // If the copy might trigger a GC, make sure that the FixedArray is
   3011     // pre-initialized with holes to make sure that it's always in a
   3012     // consistent state.
   3013     BuildFillElementsWithHole(to_elements, to_elements_kind,
   3014                               graph()->GetConstant0(), NULL);
   3015   }
   3016 
   3017   if (constant_capacity != -1) {
   3018     // Unroll the loop for small elements kinds.
   3019     for (int i = 0; i < constant_capacity; i++) {
   3020       HValue* key_constant = Add<HConstant>(i);
   3021       HInstruction* value = Add<HLoadKeyed>(
   3022           from_elements, key_constant, nullptr, nullptr, from_elements_kind);
   3023       Add<HStoreKeyed>(to_elements, key_constant, value, nullptr,
   3024                        to_elements_kind);
   3025     }
   3026   } else {
   3027     if (!pre_fill_with_holes &&
   3028         (capacity == NULL || !length->Equals(capacity))) {
   3029       BuildFillElementsWithHole(to_elements, to_elements_kind,
   3030                                 length, NULL);
   3031     }
   3032 
   3033     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   3034 
   3035     HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
   3036                                     Token::GT);
   3037 
   3038     key = AddUncasted<HSub>(key, graph()->GetConstant1());
   3039     key->ClearFlag(HValue::kCanOverflow);
   3040 
   3041     HValue* element = Add<HLoadKeyed>(from_elements, key, nullptr, nullptr,
   3042                                       from_elements_kind, ALLOW_RETURN_HOLE);
   3043 
   3044     ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
   3045                          IsFastSmiElementsKind(to_elements_kind))
   3046       ? FAST_HOLEY_ELEMENTS : to_elements_kind;
   3047 
   3048     if (IsHoleyElementsKind(from_elements_kind) &&
   3049         from_elements_kind != to_elements_kind) {
   3050       IfBuilder if_hole(this);
   3051       if_hole.If<HCompareHoleAndBranch>(element);
   3052       if_hole.Then();
   3053       HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
   3054                                      ? Add<HConstant>(HConstant::kHoleNaN)
   3055                                      : graph()->GetConstantHole();
   3056       Add<HStoreKeyed>(to_elements, key, hole_constant, nullptr, kind);
   3057       if_hole.Else();
   3058       HStoreKeyed* store =
   3059           Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
   3060       store->SetFlag(HValue::kAllowUndefinedAsNaN);
   3061       if_hole.End();
   3062     } else {
   3063       HStoreKeyed* store =
   3064           Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
   3065       store->SetFlag(HValue::kAllowUndefinedAsNaN);
   3066     }
   3067 
   3068     builder.EndBody();
   3069   }
   3070 
   3071   Counters* counters = isolate()->counters();
   3072   AddIncrementCounter(counters->inlined_copied_elements());
   3073 }
   3074 
   3075 
   3076 HValue* HGraphBuilder::BuildCloneShallowArrayCow(HValue* boilerplate,
   3077                                                  HValue* allocation_site,
   3078                                                  AllocationSiteMode mode,
   3079                                                  ElementsKind kind) {
   3080   HAllocate* array = AllocateJSArrayObject(mode);
   3081 
   3082   HValue* map = AddLoadMap(boilerplate);
   3083   HValue* elements = AddLoadElements(boilerplate);
   3084   HValue* length = AddLoadArrayLength(boilerplate, kind);
   3085 
   3086   BuildJSArrayHeader(array,
   3087                      map,
   3088                      elements,
   3089                      mode,
   3090                      FAST_ELEMENTS,
   3091                      allocation_site,
   3092                      length);
   3093   return array;
   3094 }
   3095 
   3096 
   3097 HValue* HGraphBuilder::BuildCloneShallowArrayEmpty(HValue* boilerplate,
   3098                                                    HValue* allocation_site,
   3099                                                    AllocationSiteMode mode) {
   3100   HAllocate* array = AllocateJSArrayObject(mode);
   3101 
   3102   HValue* map = AddLoadMap(boilerplate);
   3103 
   3104   BuildJSArrayHeader(array,
   3105                      map,
   3106                      NULL,  // set elements to empty fixed array
   3107                      mode,
   3108                      FAST_ELEMENTS,
   3109                      allocation_site,
   3110                      graph()->GetConstant0());
   3111   return array;
   3112 }
   3113 
   3114 
   3115 HValue* HGraphBuilder::BuildCloneShallowArrayNonEmpty(HValue* boilerplate,
   3116                                                       HValue* allocation_site,
   3117                                                       AllocationSiteMode mode,
   3118                                                       ElementsKind kind) {
   3119   HValue* boilerplate_elements = AddLoadElements(boilerplate);
   3120   HValue* capacity = AddLoadFixedArrayLength(boilerplate_elements);
   3121 
   3122   // Generate size calculation code here in order to make it dominate
   3123   // the JSArray allocation.
   3124   HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
   3125 
   3126   // Create empty JSArray object for now, store elimination should remove
   3127   // redundant initialization of elements and length fields and at the same
   3128   // time the object will be fully prepared for GC if it happens during
   3129   // elements allocation.
   3130   HValue* result = BuildCloneShallowArrayEmpty(
   3131       boilerplate, allocation_site, mode);
   3132 
   3133   HAllocate* elements = BuildAllocateElements(kind, elements_size);
   3134 
   3135   // This function implicitly relies on the fact that the
   3136   // FastCloneShallowArrayStub is called only for literals shorter than
   3137   // JSArray::kInitialMaxFastElementArray.
   3138   // Can't add HBoundsCheck here because otherwise the stub will eager a frame.
   3139   HConstant* size_upper_bound = EstablishElementsAllocationSize(
   3140       kind, JSArray::kInitialMaxFastElementArray);
   3141   elements->set_size_upper_bound(size_upper_bound);
   3142 
   3143   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(), elements);
   3144 
   3145   // The allocation for the cloned array above causes register pressure on
   3146   // machines with low register counts. Force a reload of the boilerplate
   3147   // elements here to free up a register for the allocation to avoid unnecessary
   3148   // spillage.
   3149   boilerplate_elements = AddLoadElements(boilerplate);
   3150   boilerplate_elements->SetFlag(HValue::kCantBeReplaced);
   3151 
   3152   // Copy the elements array header.
   3153   for (int i = 0; i < FixedArrayBase::kHeaderSize; i += kPointerSize) {
   3154     HObjectAccess access = HObjectAccess::ForFixedArrayHeader(i);
   3155     Add<HStoreNamedField>(
   3156         elements, access,
   3157         Add<HLoadNamedField>(boilerplate_elements, nullptr, access));
   3158   }
   3159 
   3160   // And the result of the length
   3161   HValue* length = AddLoadArrayLength(boilerplate, kind);
   3162   Add<HStoreNamedField>(result, HObjectAccess::ForArrayLength(kind), length);
   3163 
   3164   BuildCopyElements(boilerplate_elements, kind, elements,
   3165                     kind, length, NULL);
   3166   return result;
   3167 }
   3168 
   3169 
   3170 void HGraphBuilder::BuildCompareNil(HValue* value, Type* type,
   3171                                     HIfContinuation* continuation,
   3172                                     MapEmbedding map_embedding) {
   3173   IfBuilder if_nil(this);
   3174   bool some_case_handled = false;
   3175   bool some_case_missing = false;
   3176 
   3177   if (type->Maybe(Type::Null())) {
   3178     if (some_case_handled) if_nil.Or();
   3179     if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull());
   3180     some_case_handled = true;
   3181   } else {
   3182     some_case_missing = true;
   3183   }
   3184 
   3185   if (type->Maybe(Type::Undefined())) {
   3186     if (some_case_handled) if_nil.Or();
   3187     if_nil.If<HCompareObjectEqAndBranch>(value,
   3188                                          graph()->GetConstantUndefined());
   3189     some_case_handled = true;
   3190   } else {
   3191     some_case_missing = true;
   3192   }
   3193 
   3194   if (type->Maybe(Type::Undetectable())) {
   3195     if (some_case_handled) if_nil.Or();
   3196     if_nil.If<HIsUndetectableAndBranch>(value);
   3197     some_case_handled = true;
   3198   } else {
   3199     some_case_missing = true;
   3200   }
   3201 
   3202   if (some_case_missing) {
   3203     if_nil.Then();
   3204     if_nil.Else();
   3205     if (type->NumClasses() == 1) {
   3206       BuildCheckHeapObject(value);
   3207       // For ICs, the map checked below is a sentinel map that gets replaced by
   3208       // the monomorphic map when the code is used as a template to generate a
   3209       // new IC. For optimized functions, there is no sentinel map, the map
   3210       // emitted below is the actual monomorphic map.
   3211       if (map_embedding == kEmbedMapsViaWeakCells) {
   3212         HValue* cell =
   3213             Add<HConstant>(Map::WeakCellForMap(type->Classes().Current()));
   3214         HValue* expected_map = Add<HLoadNamedField>(
   3215             cell, nullptr, HObjectAccess::ForWeakCellValue());
   3216         HValue* map =
   3217             Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap());
   3218         IfBuilder map_check(this);
   3219         map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map);
   3220         map_check.ThenDeopt(Deoptimizer::kUnknownMap);
   3221         map_check.End();
   3222       } else {
   3223         DCHECK(map_embedding == kEmbedMapsDirectly);
   3224         Add<HCheckMaps>(value, type->Classes().Current());
   3225       }
   3226     } else {
   3227       if_nil.Deopt(Deoptimizer::kTooManyUndetectableTypes);
   3228     }
   3229   }
   3230 
   3231   if_nil.CaptureContinuation(continuation);
   3232 }
   3233 
   3234 
   3235 void HGraphBuilder::BuildCreateAllocationMemento(
   3236     HValue* previous_object,
   3237     HValue* previous_object_size,
   3238     HValue* allocation_site) {
   3239   DCHECK(allocation_site != NULL);
   3240   HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
   3241       previous_object, previous_object_size, HType::HeapObject());
   3242   AddStoreMapConstant(
   3243       allocation_memento, isolate()->factory()->allocation_memento_map());
   3244   Add<HStoreNamedField>(
   3245       allocation_memento,
   3246       HObjectAccess::ForAllocationMementoSite(),
   3247       allocation_site);
   3248   if (FLAG_allocation_site_pretenuring) {
   3249     HValue* memento_create_count =
   3250         Add<HLoadNamedField>(allocation_site, nullptr,
   3251                              HObjectAccess::ForAllocationSiteOffset(
   3252                                  AllocationSite::kPretenureCreateCountOffset));
   3253     memento_create_count = AddUncasted<HAdd>(
   3254         memento_create_count, graph()->GetConstant1());
   3255     // This smi value is reset to zero after every gc, overflow isn't a problem
   3256     // since the counter is bounded by the new space size.
   3257     memento_create_count->ClearFlag(HValue::kCanOverflow);
   3258     Add<HStoreNamedField>(
   3259         allocation_site, HObjectAccess::ForAllocationSiteOffset(
   3260             AllocationSite::kPretenureCreateCountOffset), memento_create_count);
   3261   }
   3262 }
   3263 
   3264 
   3265 HInstruction* HGraphBuilder::BuildGetNativeContext() {
   3266   return Add<HLoadNamedField>(
   3267       context(), nullptr,
   3268       HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
   3269 }
   3270 
   3271 
   3272 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
   3273   // Get the global object, then the native context
   3274   HInstruction* context = Add<HLoadNamedField>(
   3275       closure, nullptr, HObjectAccess::ForFunctionContextPointer());
   3276   return Add<HLoadNamedField>(
   3277       context, nullptr,
   3278       HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
   3279 }
   3280 
   3281 
   3282 HInstruction* HGraphBuilder::BuildGetScriptContext(int context_index) {
   3283   HValue* native_context = BuildGetNativeContext();
   3284   HValue* script_context_table = Add<HLoadNamedField>(
   3285       native_context, nullptr,
   3286       HObjectAccess::ForContextSlot(Context::SCRIPT_CONTEXT_TABLE_INDEX));
   3287   return Add<HLoadNamedField>(script_context_table, nullptr,
   3288                               HObjectAccess::ForScriptContext(context_index));
   3289 }
   3290 
   3291 
   3292 HValue* HGraphBuilder::BuildGetParentContext(HValue* depth, int depth_value) {
   3293   HValue* script_context = context();
   3294   if (depth != NULL) {
   3295     HValue* zero = graph()->GetConstant0();
   3296 
   3297     Push(script_context);
   3298     Push(depth);
   3299 
   3300     LoopBuilder loop(this);
   3301     loop.BeginBody(2);  // Drop script_context and depth from last environment
   3302                         // to appease live range building without simulates.
   3303     depth = Pop();
   3304     script_context = Pop();
   3305 
   3306     script_context = Add<HLoadNamedField>(
   3307         script_context, nullptr,
   3308         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   3309     depth = AddUncasted<HSub>(depth, graph()->GetConstant1());
   3310     depth->ClearFlag(HValue::kCanOverflow);
   3311 
   3312     IfBuilder if_break(this);
   3313     if_break.If<HCompareNumericAndBranch, HValue*>(depth, zero, Token::EQ);
   3314     if_break.Then();
   3315     {
   3316       Push(script_context);  // The result.
   3317       loop.Break();
   3318     }
   3319     if_break.Else();
   3320     {
   3321       Push(script_context);
   3322       Push(depth);
   3323     }
   3324     loop.EndBody();
   3325     if_break.End();
   3326 
   3327     script_context = Pop();
   3328   } else if (depth_value > 0) {
   3329     // Unroll the above loop.
   3330     for (int i = 0; i < depth_value; i++) {
   3331       script_context = Add<HLoadNamedField>(
   3332           script_context, nullptr,
   3333           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   3334     }
   3335   }
   3336   return script_context;
   3337 }
   3338 
   3339 
   3340 HInstruction* HGraphBuilder::BuildGetArrayFunction() {
   3341   HInstruction* native_context = BuildGetNativeContext();
   3342   HInstruction* index =
   3343       Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
   3344   return Add<HLoadKeyed>(native_context, index, nullptr, nullptr,
   3345                          FAST_ELEMENTS);
   3346 }
   3347 
   3348 
   3349 HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object,
   3350                                                          HValue* checked_object,
   3351                                                          FieldIndex index) {
   3352   NoObservableSideEffectsScope scope(this);
   3353   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
   3354       index.offset(), Representation::Tagged());
   3355   HInstruction* buffer = Add<HLoadNamedField>(
   3356       object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer());
   3357   HInstruction* field = Add<HLoadNamedField>(object, checked_object, access);
   3358 
   3359   HInstruction* flags = Add<HLoadNamedField>(
   3360       buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField());
   3361   HValue* was_neutered_mask =
   3362       Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
   3363   HValue* was_neutered_test =
   3364       AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);
   3365 
   3366   IfBuilder if_was_neutered(this);
   3367   if_was_neutered.If<HCompareNumericAndBranch>(
   3368       was_neutered_test, graph()->GetConstant0(), Token::NE);
   3369   if_was_neutered.Then();
   3370   Push(graph()->GetConstant0());
   3371   if_was_neutered.Else();
   3372   Push(field);
   3373   if_was_neutered.End();
   3374 
   3375   return Pop();
   3376 }
   3377 
   3378 
   3379 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
   3380     ElementsKind kind,
   3381     HValue* allocation_site_payload,
   3382     HValue* constructor_function,
   3383     AllocationSiteOverrideMode override_mode) :
   3384         builder_(builder),
   3385         kind_(kind),
   3386         allocation_site_payload_(allocation_site_payload),
   3387         constructor_function_(constructor_function) {
   3388   DCHECK(!allocation_site_payload->IsConstant() ||
   3389          HConstant::cast(allocation_site_payload)->handle(
   3390              builder_->isolate())->IsAllocationSite());
   3391   mode_ = override_mode == DISABLE_ALLOCATION_SITES
   3392       ? DONT_TRACK_ALLOCATION_SITE
   3393       : AllocationSite::GetMode(kind);
   3394 }
   3395 
   3396 
   3397 HGraphBuilder::JSArrayBuilder::JSArrayBuilder(HGraphBuilder* builder,
   3398                                               ElementsKind kind,
   3399                                               HValue* constructor_function) :
   3400     builder_(builder),
   3401     kind_(kind),
   3402     mode_(DONT_TRACK_ALLOCATION_SITE),
   3403     allocation_site_payload_(NULL),
   3404     constructor_function_(constructor_function) {
   3405 }
   3406 
   3407 
   3408 HValue* HGraphBuilder::JSArrayBuilder::EmitMapCode() {
   3409   if (!builder()->top_info()->IsStub()) {
   3410     // A constant map is fine.
   3411     Handle<Map> map(builder()->isolate()->get_initial_js_array_map(kind_),
   3412                     builder()->isolate());
   3413     return builder()->Add<HConstant>(map);
   3414   }
   3415 
   3416   if (constructor_function_ != NULL && kind_ == GetInitialFastElementsKind()) {
   3417     // No need for a context lookup if the kind_ matches the initial
   3418     // map, because we can just load the map in that case.
   3419     HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
   3420     return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
   3421                                            access);
   3422   }
   3423 
   3424   // TODO(mvstanton): we should always have a constructor function if we
   3425   // are creating a stub.
   3426   HInstruction* native_context = constructor_function_ != NULL
   3427       ? builder()->BuildGetNativeContext(constructor_function_)
   3428       : builder()->BuildGetNativeContext();
   3429 
   3430   HObjectAccess access =
   3431       HObjectAccess::ForContextSlot(Context::ArrayMapIndex(kind_));
   3432   return builder()->Add<HLoadNamedField>(native_context, nullptr, access);
   3433 }
   3434 
   3435 
   3436 HValue* HGraphBuilder::JSArrayBuilder::EmitInternalMapCode() {
   3437   // Find the map near the constructor function
   3438   HObjectAccess access = HObjectAccess::ForPrototypeOrInitialMap();
   3439   return builder()->Add<HLoadNamedField>(constructor_function_, nullptr,
   3440                                          access);
   3441 }
   3442 
   3443 
   3444 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateEmptyArray() {
   3445   HConstant* capacity = builder()->Add<HConstant>(initial_capacity());
   3446   return AllocateArray(capacity,
   3447                        capacity,
   3448                        builder()->graph()->GetConstant0());
   3449 }
   3450 
   3451 
   3452 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
   3453     HValue* capacity,
   3454     HConstant* capacity_upper_bound,
   3455     HValue* length_field,
   3456     FillMode fill_mode) {
   3457   return AllocateArray(capacity,
   3458                        capacity_upper_bound->GetInteger32Constant(),
   3459                        length_field,
   3460                        fill_mode);
   3461 }
   3462 
   3463 
   3464 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
   3465     HValue* capacity,
   3466     int capacity_upper_bound,
   3467     HValue* length_field,
   3468     FillMode fill_mode) {
   3469   HConstant* elememts_size_upper_bound = capacity->IsInteger32Constant()
   3470       ? HConstant::cast(capacity)
   3471       : builder()->EstablishElementsAllocationSize(kind_, capacity_upper_bound);
   3472 
   3473   HAllocate* array = AllocateArray(capacity, length_field, fill_mode);
   3474   if (!elements_location_->has_size_upper_bound()) {
   3475     elements_location_->set_size_upper_bound(elememts_size_upper_bound);
   3476   }
   3477   return array;
   3478 }
   3479 
   3480 
   3481 HAllocate* HGraphBuilder::JSArrayBuilder::AllocateArray(
   3482     HValue* capacity,
   3483     HValue* length_field,
   3484     FillMode fill_mode) {
   3485   // These HForceRepresentations are because we store these as fields in the
   3486   // objects we construct, and an int32-to-smi HChange could deopt. Accept
   3487   // the deopt possibility now, before allocation occurs.
   3488   capacity =
   3489       builder()->AddUncasted<HForceRepresentation>(capacity,
   3490                                                    Representation::Smi());
   3491   length_field =
   3492       builder()->AddUncasted<HForceRepresentation>(length_field,
   3493                                                    Representation::Smi());
   3494 
   3495   // Generate size calculation code here in order to make it dominate
   3496   // the JSArray allocation.
   3497   HValue* elements_size =
   3498       builder()->BuildCalculateElementsSize(kind_, capacity);
   3499 
   3500   // Bail out for large objects.
   3501   HValue* max_regular_heap_object_size =
   3502       builder()->Add<HConstant>(Page::kMaxRegularHeapObjectSize);
   3503   builder()->Add<HBoundsCheck>(elements_size, max_regular_heap_object_size);
   3504 
   3505   // Allocate (dealing with failure appropriately)
   3506   HAllocate* array_object = builder()->AllocateJSArrayObject(mode_);
   3507 
   3508   // Fill in the fields: map, properties, length
   3509   HValue* map;
   3510   if (allocation_site_payload_ == NULL) {
   3511     map = EmitInternalMapCode();
   3512   } else {
   3513     map = EmitMapCode();
   3514   }
   3515 
   3516   builder()->BuildJSArrayHeader(array_object,
   3517                                 map,
   3518                                 NULL,  // set elements to empty fixed array
   3519                                 mode_,
   3520                                 kind_,
   3521                                 allocation_site_payload_,
   3522                                 length_field);
   3523 
   3524   // Allocate and initialize the elements
   3525   elements_location_ = builder()->BuildAllocateElements(kind_, elements_size);
   3526 
   3527   builder()->BuildInitializeElementsHeader(elements_location_, kind_, capacity);
   3528 
   3529   // Set the elements
   3530   builder()->Add<HStoreNamedField>(
   3531       array_object, HObjectAccess::ForElementsPointer(), elements_location_);
   3532 
   3533   if (fill_mode == FILL_WITH_HOLE) {
   3534     builder()->BuildFillElementsWithHole(elements_location_, kind_,
   3535                                          graph()->GetConstant0(), capacity);
   3536   }
   3537 
   3538   return array_object;
   3539 }
   3540 
   3541 
   3542 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) {
   3543   HValue* native_context = BuildGetNativeContext();
   3544   HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index);
   3545   return Add<HLoadNamedField>(native_context, nullptr, function_access);
   3546 }
   3547 
   3548 
   3549 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info)
   3550     : HGraphBuilder(info),
   3551       function_state_(NULL),
   3552       initial_function_state_(this, info, NORMAL_RETURN, 0),
   3553       ast_context_(NULL),
   3554       break_scope_(NULL),
   3555       inlined_count_(0),
   3556       globals_(10, info->zone()),
   3557       osr_(new(info->zone()) HOsrBuilder(this)) {
   3558   // This is not initialized in the initializer list because the
   3559   // constructor for the initial state relies on function_state_ == NULL
   3560   // to know it's the initial state.
   3561   function_state_ = &initial_function_state_;
   3562   InitializeAstVisitor(info->isolate());
   3563   if (top_info()->is_tracking_positions()) {
   3564     SetSourcePosition(info->shared_info()->start_position());
   3565   }
   3566 }
   3567 
   3568 
   3569 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
   3570                                                 HBasicBlock* second,
   3571                                                 BailoutId join_id) {
   3572   if (first == NULL) {
   3573     return second;
   3574   } else if (second == NULL) {
   3575     return first;
   3576   } else {
   3577     HBasicBlock* join_block = graph()->CreateBasicBlock();
   3578     Goto(first, join_block);
   3579     Goto(second, join_block);
   3580     join_block->SetJoinId(join_id);
   3581     return join_block;
   3582   }
   3583 }
   3584 
   3585 
   3586 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
   3587                                                   HBasicBlock* exit_block,
   3588                                                   HBasicBlock* continue_block) {
   3589   if (continue_block != NULL) {
   3590     if (exit_block != NULL) Goto(exit_block, continue_block);
   3591     continue_block->SetJoinId(statement->ContinueId());
   3592     return continue_block;
   3593   }
   3594   return exit_block;
   3595 }
   3596 
   3597 
   3598 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
   3599                                                 HBasicBlock* loop_entry,
   3600                                                 HBasicBlock* body_exit,
   3601                                                 HBasicBlock* loop_successor,
   3602                                                 HBasicBlock* break_block) {
   3603   if (body_exit != NULL) Goto(body_exit, loop_entry);
   3604   loop_entry->PostProcessLoopHeader(statement);
   3605   if (break_block != NULL) {
   3606     if (loop_successor != NULL) Goto(loop_successor, break_block);
   3607     break_block->SetJoinId(statement->ExitId());
   3608     return break_block;
   3609   }
   3610   return loop_successor;
   3611 }
   3612 
   3613 
   3614 // Build a new loop header block and set it as the current block.
   3615 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
   3616   HBasicBlock* loop_entry = CreateLoopHeaderBlock();
   3617   Goto(loop_entry);
   3618   set_current_block(loop_entry);
   3619   return loop_entry;
   3620 }
   3621 
   3622 
   3623 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
   3624     IterationStatement* statement) {
   3625   HBasicBlock* loop_entry = osr()->HasOsrEntryAt(statement)
   3626       ? osr()->BuildOsrLoopEntry(statement)
   3627       : BuildLoopEntry();
   3628   return loop_entry;
   3629 }
   3630 
   3631 
   3632 void HBasicBlock::FinishExit(HControlInstruction* instruction,
   3633                              SourcePosition position) {
   3634   Finish(instruction, position);
   3635   ClearEnvironment();
   3636 }
   3637 
   3638 
   3639 std::ostream& operator<<(std::ostream& os, const HBasicBlock& b) {
   3640   return os << "B" << b.block_id();
   3641 }
   3642 
   3643 
   3644 HGraph::HGraph(CompilationInfo* info)
   3645     : isolate_(info->isolate()),
   3646       next_block_id_(0),
   3647       entry_block_(NULL),
   3648       blocks_(8, info->zone()),
   3649       values_(16, info->zone()),
   3650       phi_list_(NULL),
   3651       uint32_instructions_(NULL),
   3652       osr_(NULL),
   3653       info_(info),
   3654       zone_(info->zone()),
   3655       is_recursive_(false),
   3656       use_optimistic_licm_(false),
   3657       depends_on_empty_array_proto_elements_(false),
   3658       type_change_checksum_(0),
   3659       maximum_environment_size_(0),
   3660       no_side_effects_scope_count_(0),
   3661       disallow_adding_new_values_(false) {
   3662   if (info->IsStub()) {
   3663     CallInterfaceDescriptor descriptor =
   3664         info->code_stub()->GetCallInterfaceDescriptor();
   3665     start_environment_ =
   3666         new (zone_) HEnvironment(zone_, descriptor.GetRegisterParameterCount());
   3667   } else {
   3668     if (info->is_tracking_positions()) {
   3669       info->TraceInlinedFunction(info->shared_info(), SourcePosition::Unknown(),
   3670                                  InlinedFunctionInfo::kNoParentId);
   3671     }
   3672     start_environment_ =
   3673         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
   3674   }
   3675   start_environment_->set_ast_id(BailoutId::FunctionContext());
   3676   entry_block_ = CreateBasicBlock();
   3677   entry_block_->SetInitialEnvironment(start_environment_);
   3678 }
   3679 
   3680 
   3681 HBasicBlock* HGraph::CreateBasicBlock() {
   3682   HBasicBlock* result = new(zone()) HBasicBlock(this);
   3683   blocks_.Add(result, zone());
   3684   return result;
   3685 }
   3686 
   3687 
   3688 void HGraph::FinalizeUniqueness() {
   3689   DisallowHeapAllocation no_gc;
   3690   for (int i = 0; i < blocks()->length(); ++i) {
   3691     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
   3692       it.Current()->FinalizeUniqueness();
   3693     }
   3694   }
   3695 }
   3696 
   3697 
   3698 int HGraph::SourcePositionToScriptPosition(SourcePosition pos) {
   3699   return (FLAG_hydrogen_track_positions && !pos.IsUnknown())
   3700              ? info()->start_position_for(pos.inlining_id()) + pos.position()
   3701              : pos.raw();
   3702 }
   3703 
   3704 
   3705 // Block ordering was implemented with two mutually recursive methods,
   3706 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
   3707 // The recursion could lead to stack overflow so the algorithm has been
   3708 // implemented iteratively.
   3709 // At a high level the algorithm looks like this:
   3710 //
   3711 // Postorder(block, loop_header) : {
   3712 //   if (block has already been visited or is of another loop) return;
   3713 //   mark block as visited;
   3714 //   if (block is a loop header) {
   3715 //     VisitLoopMembers(block, loop_header);
   3716 //     VisitSuccessorsOfLoopHeader(block);
   3717 //   } else {
   3718 //     VisitSuccessors(block)
   3719 //   }
   3720 //   put block in result list;
   3721 // }
   3722 //
   3723 // VisitLoopMembers(block, outer_loop_header) {
   3724 //   foreach (block b in block loop members) {
   3725 //     VisitSuccessorsOfLoopMember(b, outer_loop_header);
   3726 //     if (b is loop header) VisitLoopMembers(b);
   3727 //   }
   3728 // }
   3729 //
   3730 // VisitSuccessorsOfLoopMember(block, outer_loop_header) {
   3731 //   foreach (block b in block successors) Postorder(b, outer_loop_header)
   3732 // }
   3733 //
   3734 // VisitSuccessorsOfLoopHeader(block) {
   3735 //   foreach (block b in block successors) Postorder(b, block)
   3736 // }
   3737 //
   3738 // VisitSuccessors(block, loop_header) {
   3739 //   foreach (block b in block successors) Postorder(b, loop_header)
   3740 // }
   3741 //
   3742 // The ordering is started calling Postorder(entry, NULL).
   3743 //
   3744 // Each instance of PostorderProcessor represents the "stack frame" of the
   3745 // recursion, and particularly keeps the state of the loop (iteration) of the
   3746 // "Visit..." function it represents.
   3747 // To recycle memory we keep all the frames in a double linked list but
   3748 // this means that we cannot use constructors to initialize the frames.
   3749 //
   3750 class PostorderProcessor : public ZoneObject {
   3751  public:
   3752   // Back link (towards the stack bottom).
   3753   PostorderProcessor* parent() {return father_; }
   3754   // Forward link (towards the stack top).
   3755   PostorderProcessor* child() {return child_; }
   3756   HBasicBlock* block() { return block_; }
   3757   HLoopInformation* loop() { return loop_; }
   3758   HBasicBlock* loop_header() { return loop_header_; }
   3759 
   3760   static PostorderProcessor* CreateEntryProcessor(Zone* zone,
   3761                                                   HBasicBlock* block) {
   3762     PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
   3763     return result->SetupSuccessors(zone, block, NULL);
   3764   }
   3765 
   3766   PostorderProcessor* PerformStep(Zone* zone,
   3767                                   ZoneList<HBasicBlock*>* order) {
   3768     PostorderProcessor* next =
   3769         PerformNonBacktrackingStep(zone, order);
   3770     if (next != NULL) {
   3771       return next;
   3772     } else {
   3773       return Backtrack(zone, order);
   3774     }
   3775   }
   3776 
   3777  private:
   3778   explicit PostorderProcessor(PostorderProcessor* father)
   3779       : father_(father), child_(NULL), successor_iterator(NULL) { }
   3780 
   3781   // Each enum value states the cycle whose state is kept by this instance.
   3782   enum LoopKind {
   3783     NONE,
   3784     SUCCESSORS,
   3785     SUCCESSORS_OF_LOOP_HEADER,
   3786     LOOP_MEMBERS,
   3787     SUCCESSORS_OF_LOOP_MEMBER
   3788   };
   3789 
   3790   // Each "Setup..." method is like a constructor for a cycle state.
   3791   PostorderProcessor* SetupSuccessors(Zone* zone,
   3792                                       HBasicBlock* block,
   3793                                       HBasicBlock* loop_header) {
   3794     if (block == NULL || block->IsOrdered() ||
   3795         block->parent_loop_header() != loop_header) {
   3796       kind_ = NONE;
   3797       block_ = NULL;
   3798       loop_ = NULL;
   3799       loop_header_ = NULL;
   3800       return this;
   3801     } else {
   3802       block_ = block;
   3803       loop_ = NULL;
   3804       block->MarkAsOrdered();
   3805 
   3806       if (block->IsLoopHeader()) {
   3807         kind_ = SUCCESSORS_OF_LOOP_HEADER;
   3808         loop_header_ = block;
   3809         InitializeSuccessors();
   3810         PostorderProcessor* result = Push(zone);
   3811         return result->SetupLoopMembers(zone, block, block->loop_information(),
   3812                                         loop_header);
   3813       } else {
   3814         DCHECK(block->IsFinished());
   3815         kind_ = SUCCESSORS;
   3816         loop_header_ = loop_header;
   3817         InitializeSuccessors();
   3818         return this;
   3819       }
   3820     }
   3821   }
   3822 
   3823   PostorderProcessor* SetupLoopMembers(Zone* zone,
   3824                                        HBasicBlock* block,
   3825                                        HLoopInformation* loop,
   3826                                        HBasicBlock* loop_header) {
   3827     kind_ = LOOP_MEMBERS;
   3828     block_ = block;
   3829     loop_ = loop;
   3830     loop_header_ = loop_header;
   3831     InitializeLoopMembers();
   3832     return this;
   3833   }
   3834 
   3835   PostorderProcessor* SetupSuccessorsOfLoopMember(
   3836       HBasicBlock* block,
   3837       HLoopInformation* loop,
   3838       HBasicBlock* loop_header) {
   3839     kind_ = SUCCESSORS_OF_LOOP_MEMBER;
   3840     block_ = block;
   3841     loop_ = loop;
   3842     loop_header_ = loop_header;
   3843     InitializeSuccessors();
   3844     return this;
   3845   }
   3846 
   3847   // This method "allocates" a new stack frame.
   3848   PostorderProcessor* Push(Zone* zone) {
   3849     if (child_ == NULL) {
   3850       child_ = new(zone) PostorderProcessor(this);
   3851     }
   3852     return child_;
   3853   }
   3854 
   3855   void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) {
   3856     DCHECK(block_->end()->FirstSuccessor() == NULL ||
   3857            order->Contains(block_->end()->FirstSuccessor()) ||
   3858            block_->end()->FirstSuccessor()->IsLoopHeader());
   3859     DCHECK(block_->end()->SecondSuccessor() == NULL ||
   3860            order->Contains(block_->end()->SecondSuccessor()) ||
   3861            block_->end()->SecondSuccessor()->IsLoopHeader());
   3862     order->Add(block_, zone);
   3863   }
   3864 
   3865   // This method is the basic block to walk up the stack.
   3866   PostorderProcessor* Pop(Zone* zone,
   3867                           ZoneList<HBasicBlock*>* order) {
   3868     switch (kind_) {
   3869       case SUCCESSORS:
   3870       case SUCCESSORS_OF_LOOP_HEADER:
   3871         ClosePostorder(order, zone);
   3872         return father_;
   3873       case LOOP_MEMBERS:
   3874         return father_;
   3875       case SUCCESSORS_OF_LOOP_MEMBER:
   3876         if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
   3877           // In this case we need to perform a LOOP_MEMBERS cycle so we
   3878           // initialize it and return this instead of father.
   3879           return SetupLoopMembers(zone, block(),
   3880                                   block()->loop_information(), loop_header_);
   3881         } else {
   3882           return father_;
   3883         }
   3884       case NONE:
   3885         return father_;
   3886     }
   3887     UNREACHABLE();
   3888     return NULL;
   3889   }
   3890 
   3891   // Walks up the stack.
   3892   PostorderProcessor* Backtrack(Zone* zone,
   3893                                 ZoneList<HBasicBlock*>* order) {
   3894     PostorderProcessor* parent = Pop(zone, order);
   3895     while (parent != NULL) {
   3896       PostorderProcessor* next =
   3897           parent->PerformNonBacktrackingStep(zone, order);
   3898       if (next != NULL) {
   3899         return next;
   3900       } else {
   3901         parent = parent->Pop(zone, order);
   3902       }
   3903     }
   3904     return NULL;
   3905   }
   3906 
   3907   PostorderProcessor* PerformNonBacktrackingStep(
   3908       Zone* zone,
   3909       ZoneList<HBasicBlock*>* order) {
   3910     HBasicBlock* next_block;
   3911     switch (kind_) {
   3912       case SUCCESSORS:
   3913         next_block = AdvanceSuccessors();
   3914         if (next_block != NULL) {
   3915           PostorderProcessor* result = Push(zone);
   3916           return result->SetupSuccessors(zone, next_block, loop_header_);
   3917         }
   3918         break;
   3919       case SUCCESSORS_OF_LOOP_HEADER:
   3920         next_block = AdvanceSuccessors();
   3921         if (next_block != NULL) {
   3922           PostorderProcessor* result = Push(zone);
   3923           return result->SetupSuccessors(zone, next_block, block());
   3924         }
   3925         break;
   3926       case LOOP_MEMBERS:
   3927         next_block = AdvanceLoopMembers();
   3928         if (next_block != NULL) {
   3929           PostorderProcessor* result = Push(zone);
   3930           return result->SetupSuccessorsOfLoopMember(next_block,
   3931                                                      loop_, loop_header_);
   3932         }
   3933         break;
   3934       case SUCCESSORS_OF_LOOP_MEMBER:
   3935         next_block = AdvanceSuccessors();
   3936         if (next_block != NULL) {
   3937           PostorderProcessor* result = Push(zone);
   3938           return result->SetupSuccessors(zone, next_block, loop_header_);
   3939         }
   3940         break;
   3941       case NONE:
   3942         return NULL;
   3943     }
   3944     return NULL;
   3945   }
   3946 
   3947   // The following two methods implement a "foreach b in successors" cycle.
   3948   void InitializeSuccessors() {
   3949     loop_index = 0;
   3950     loop_length = 0;
   3951     successor_iterator = HSuccessorIterator(block_->end());
   3952   }
   3953 
   3954   HBasicBlock* AdvanceSuccessors() {
   3955     if (!successor_iterator.Done()) {
   3956       HBasicBlock* result = successor_iterator.Current();
   3957       successor_iterator.Advance();
   3958       return result;
   3959     }
   3960     return NULL;
   3961   }
   3962 
   3963   // The following two methods implement a "foreach b in loop members" cycle.
   3964   void InitializeLoopMembers() {
   3965     loop_index = 0;
   3966     loop_length = loop_->blocks()->length();
   3967   }
   3968 
   3969   HBasicBlock* AdvanceLoopMembers() {
   3970     if (loop_index < loop_length) {
   3971       HBasicBlock* result = loop_->blocks()->at(loop_index);
   3972       loop_index++;
   3973       return result;
   3974     } else {
   3975       return NULL;
   3976     }
   3977   }
   3978 
   3979   LoopKind kind_;
   3980   PostorderProcessor* father_;
   3981   PostorderProcessor* child_;
   3982   HLoopInformation* loop_;
   3983   HBasicBlock* block_;
   3984   HBasicBlock* loop_header_;
   3985   int loop_index;
   3986   int loop_length;
   3987   HSuccessorIterator successor_iterator;
   3988 };
   3989 
   3990 
   3991 void HGraph::OrderBlocks() {
   3992   CompilationPhase phase("H_Block ordering", info());
   3993 
   3994 #ifdef DEBUG
   3995   // Initially the blocks must not be ordered.
   3996   for (int i = 0; i < blocks_.length(); ++i) {
   3997     DCHECK(!blocks_[i]->IsOrdered());
   3998   }
   3999 #endif
   4000 
   4001   PostorderProcessor* postorder =
   4002       PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
   4003   blocks_.Rewind(0);
   4004   while (postorder) {
   4005     postorder = postorder->PerformStep(zone(), &blocks_);
   4006   }
   4007 
   4008 #ifdef DEBUG
   4009   // Now all blocks must be marked as ordered.
   4010   for (int i = 0; i < blocks_.length(); ++i) {
   4011     DCHECK(blocks_[i]->IsOrdered());
   4012   }
   4013 #endif
   4014 
   4015   // Reverse block list and assign block IDs.
   4016   for (int i = 0, j = blocks_.length(); --j >= i; ++i) {
   4017     HBasicBlock* bi = blocks_[i];
   4018     HBasicBlock* bj = blocks_[j];
   4019     bi->set_block_id(j);
   4020     bj->set_block_id(i);
   4021     blocks_[i] = bj;
   4022     blocks_[j] = bi;
   4023   }
   4024 }
   4025 
   4026 
   4027 void HGraph::AssignDominators() {
   4028   HPhase phase("H_Assign dominators", this);
   4029   for (int i = 0; i < blocks_.length(); ++i) {
   4030     HBasicBlock* block = blocks_[i];
   4031     if (block->IsLoopHeader()) {
   4032       // Only the first predecessor of a loop header is from outside the loop.
   4033       // All others are back edges, and thus cannot dominate the loop header.
   4034       block->AssignCommonDominator(block->predecessors()->first());
   4035       block->AssignLoopSuccessorDominators();
   4036     } else {
   4037       for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
   4038         blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
   4039       }
   4040     }
   4041   }
   4042 }
   4043 
   4044 
   4045 bool HGraph::CheckArgumentsPhiUses() {
   4046   int block_count = blocks_.length();
   4047   for (int i = 0; i < block_count; ++i) {
   4048     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   4049       HPhi* phi = blocks_[i]->phis()->at(j);
   4050       // We don't support phi uses of arguments for now.
   4051       if (phi->CheckFlag(HValue::kIsArguments)) return false;
   4052     }
   4053   }
   4054   return true;
   4055 }
   4056 
   4057 
   4058 bool HGraph::CheckConstPhiUses() {
   4059   int block_count = blocks_.length();
   4060   for (int i = 0; i < block_count; ++i) {
   4061     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   4062       HPhi* phi = blocks_[i]->phis()->at(j);
   4063       // Check for the hole value (from an uninitialized const).
   4064       for (int k = 0; k < phi->OperandCount(); k++) {
   4065         if (phi->OperandAt(k) == GetConstantHole()) return false;
   4066       }
   4067     }
   4068   }
   4069   return true;
   4070 }
   4071 
   4072 
   4073 void HGraph::CollectPhis() {
   4074   int block_count = blocks_.length();
   4075   phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
   4076   for (int i = 0; i < block_count; ++i) {
   4077     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   4078       HPhi* phi = blocks_[i]->phis()->at(j);
   4079       phi_list_->Add(phi, zone());
   4080     }
   4081   }
   4082 }
   4083 
   4084 
   4085 // Implementation of utility class to encapsulate the translation state for
   4086 // a (possibly inlined) function.
   4087 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
   4088                              CompilationInfo* info, InliningKind inlining_kind,
   4089                              int inlining_id)
   4090     : owner_(owner),
   4091       compilation_info_(info),
   4092       call_context_(NULL),
   4093       inlining_kind_(inlining_kind),
   4094       function_return_(NULL),
   4095       test_context_(NULL),
   4096       entry_(NULL),
   4097       arguments_object_(NULL),
   4098       arguments_elements_(NULL),
   4099       inlining_id_(inlining_id),
   4100       outer_source_position_(SourcePosition::Unknown()),
   4101       outer_(owner->function_state()) {
   4102   if (outer_ != NULL) {
   4103     // State for an inline function.
   4104     if (owner->ast_context()->IsTest()) {
   4105       HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
   4106       HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
   4107       if_true->MarkAsInlineReturnTarget(owner->current_block());
   4108       if_false->MarkAsInlineReturnTarget(owner->current_block());
   4109       TestContext* outer_test_context = TestContext::cast(owner->ast_context());
   4110       Expression* cond = outer_test_context->condition();
   4111       // The AstContext constructor pushed on the context stack.  This newed
   4112       // instance is the reason that AstContext can't be BASE_EMBEDDED.
   4113       test_context_ = new TestContext(owner, cond, if_true, if_false);
   4114     } else {
   4115       function_return_ = owner->graph()->CreateBasicBlock();
   4116       function_return()->MarkAsInlineReturnTarget(owner->current_block());
   4117     }
   4118     // Set this after possibly allocating a new TestContext above.
   4119     call_context_ = owner->ast_context();
   4120   }
   4121 
   4122   // Push on the state stack.
   4123   owner->set_function_state(this);
   4124 
   4125   if (compilation_info_->is_tracking_positions()) {
   4126     outer_source_position_ = owner->source_position();
   4127     owner->EnterInlinedSource(
   4128       info->shared_info()->start_position(),
   4129       inlining_id);
   4130     owner->SetSourcePosition(info->shared_info()->start_position());
   4131   }
   4132 }
   4133 
   4134 
   4135 FunctionState::~FunctionState() {
   4136   delete test_context_;
   4137   owner_->set_function_state(outer_);
   4138 
   4139   if (compilation_info_->is_tracking_positions()) {
   4140     owner_->set_source_position(outer_source_position_);
   4141     owner_->EnterInlinedSource(
   4142       outer_->compilation_info()->shared_info()->start_position(),
   4143       outer_->inlining_id());
   4144   }
   4145 }
   4146 
   4147 
   4148 // Implementation of utility classes to represent an expression's context in
   4149 // the AST.
   4150 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
   4151     : owner_(owner),
   4152       kind_(kind),
   4153       outer_(owner->ast_context()),
   4154       typeof_mode_(NOT_INSIDE_TYPEOF) {
   4155   owner->set_ast_context(this);  // Push.
   4156 #ifdef DEBUG
   4157   DCHECK(owner->environment()->frame_type() == JS_FUNCTION);
   4158   original_length_ = owner->environment()->length();
   4159 #endif
   4160 }
   4161 
   4162 
   4163 AstContext::~AstContext() {
   4164   owner_->set_ast_context(outer_);  // Pop.
   4165 }
   4166 
   4167 
   4168 EffectContext::~EffectContext() {
   4169   DCHECK(owner()->HasStackOverflow() ||
   4170          owner()->current_block() == NULL ||
   4171          (owner()->environment()->length() == original_length_ &&
   4172           owner()->environment()->frame_type() == JS_FUNCTION));
   4173 }
   4174 
   4175 
   4176 ValueContext::~ValueContext() {
   4177   DCHECK(owner()->HasStackOverflow() ||
   4178          owner()->current_block() == NULL ||
   4179          (owner()->environment()->length() == original_length_ + 1 &&
   4180           owner()->environment()->frame_type() == JS_FUNCTION));
   4181 }
   4182 
   4183 
   4184 void EffectContext::ReturnValue(HValue* value) {
   4185   // The value is simply ignored.
   4186 }
   4187 
   4188 
   4189 void ValueContext::ReturnValue(HValue* value) {
   4190   // The value is tracked in the bailout environment, and communicated
   4191   // through the environment as the result of the expression.
   4192   if (value->CheckFlag(HValue::kIsArguments)) {
   4193     if (flag_ == ARGUMENTS_FAKED) {
   4194       value = owner()->graph()->GetConstantUndefined();
   4195     } else if (!arguments_allowed()) {
   4196       owner()->Bailout(kBadValueContextForArgumentsValue);
   4197     }
   4198   }
   4199   owner()->Push(value);
   4200 }
   4201 
   4202 
   4203 void TestContext::ReturnValue(HValue* value) {
   4204   BuildBranch(value);
   4205 }
   4206 
   4207 
   4208 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   4209   DCHECK(!instr->IsControlInstruction());
   4210   owner()->AddInstruction(instr);
   4211   if (instr->HasObservableSideEffects()) {
   4212     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   4213   }
   4214 }
   4215 
   4216 
   4217 void EffectContext::ReturnControl(HControlInstruction* instr,
   4218                                   BailoutId ast_id) {
   4219   DCHECK(!instr->HasObservableSideEffects());
   4220   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
   4221   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
   4222   instr->SetSuccessorAt(0, empty_true);
   4223   instr->SetSuccessorAt(1, empty_false);
   4224   owner()->FinishCurrentBlock(instr);
   4225   HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
   4226   owner()->set_current_block(join);
   4227 }
   4228 
   4229 
   4230 void EffectContext::ReturnContinuation(HIfContinuation* continuation,
   4231                                        BailoutId ast_id) {
   4232   HBasicBlock* true_branch = NULL;
   4233   HBasicBlock* false_branch = NULL;
   4234   continuation->Continue(&true_branch, &false_branch);
   4235   if (!continuation->IsTrueReachable()) {
   4236     owner()->set_current_block(false_branch);
   4237   } else if (!continuation->IsFalseReachable()) {
   4238     owner()->set_current_block(true_branch);
   4239   } else {
   4240     HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
   4241     owner()->set_current_block(join);
   4242   }
   4243 }
   4244 
   4245 
   4246 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   4247   DCHECK(!instr->IsControlInstruction());
   4248   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
   4249     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
   4250   }
   4251   owner()->AddInstruction(instr);
   4252   owner()->Push(instr);
   4253   if (instr->HasObservableSideEffects()) {
   4254     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   4255   }
   4256 }
   4257 
   4258 
   4259 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
   4260   DCHECK(!instr->HasObservableSideEffects());
   4261   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
   4262     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
   4263   }
   4264   HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
   4265   HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
   4266   instr->SetSuccessorAt(0, materialize_true);
   4267   instr->SetSuccessorAt(1, materialize_false);
   4268   owner()->FinishCurrentBlock(instr);
   4269   owner()->set_current_block(materialize_true);
   4270   owner()->Push(owner()->graph()->GetConstantTrue());
   4271   owner()->set_current_block(materialize_false);
   4272   owner()->Push(owner()->graph()->GetConstantFalse());
   4273   HBasicBlock* join =
   4274     owner()->CreateJoin(materialize_true, materialize_false, ast_id);
   4275   owner()->set_current_block(join);
   4276 }
   4277 
   4278 
   4279 void ValueContext::ReturnContinuation(HIfContinuation* continuation,
   4280                                       BailoutId ast_id) {
   4281   HBasicBlock* materialize_true = NULL;
   4282   HBasicBlock* materialize_false = NULL;
   4283   continuation->Continue(&materialize_true, &materialize_false);
   4284   if (continuation->IsTrueReachable()) {
   4285     owner()->set_current_block(materialize_true);
   4286     owner()->Push(owner()->graph()->GetConstantTrue());
   4287     owner()->set_current_block(materialize_true);
   4288   }
   4289   if (continuation->IsFalseReachable()) {
   4290     owner()->set_current_block(materialize_false);
   4291     owner()->Push(owner()->graph()->GetConstantFalse());
   4292     owner()->set_current_block(materialize_false);
   4293   }
   4294   if (continuation->TrueAndFalseReachable()) {
   4295     HBasicBlock* join =
   4296         owner()->CreateJoin(materialize_true, materialize_false, ast_id);
   4297     owner()->set_current_block(join);
   4298   }
   4299 }
   4300 
   4301 
   4302 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   4303   DCHECK(!instr->IsControlInstruction());
   4304   HOptimizedGraphBuilder* builder = owner();
   4305   builder->AddInstruction(instr);
   4306   // We expect a simulate after every expression with side effects, though
   4307   // this one isn't actually needed (and wouldn't work if it were targeted).
   4308   if (instr->HasObservableSideEffects()) {
   4309     builder->Push(instr);
   4310     builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   4311     builder->Pop();
   4312   }
   4313   BuildBranch(instr);
   4314 }
   4315 
   4316 
   4317 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
   4318   DCHECK(!instr->HasObservableSideEffects());
   4319   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
   4320   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
   4321   instr->SetSuccessorAt(0, empty_true);
   4322   instr->SetSuccessorAt(1, empty_false);
   4323   owner()->FinishCurrentBlock(instr);
   4324   owner()->Goto(empty_true, if_true(), owner()->function_state());
   4325   owner()->Goto(empty_false, if_false(), owner()->function_state());
   4326   owner()->set_current_block(NULL);
   4327 }
   4328 
   4329 
   4330 void TestContext::ReturnContinuation(HIfContinuation* continuation,
   4331                                      BailoutId ast_id) {
   4332   HBasicBlock* true_branch = NULL;
   4333   HBasicBlock* false_branch = NULL;
   4334   continuation->Continue(&true_branch, &false_branch);
   4335   if (continuation->IsTrueReachable()) {
   4336     owner()->Goto(true_branch, if_true(), owner()->function_state());
   4337   }
   4338   if (continuation->IsFalseReachable()) {
   4339     owner()->Goto(false_branch, if_false(), owner()->function_state());
   4340   }
   4341   owner()->set_current_block(NULL);
   4342 }
   4343 
   4344 
   4345 void TestContext::BuildBranch(HValue* value) {
   4346   // We expect the graph to be in edge-split form: there is no edge that
   4347   // connects a branch node to a join node.  We conservatively ensure that
   4348   // property by always adding an empty block on the outgoing edges of this
   4349   // branch.
   4350   HOptimizedGraphBuilder* builder = owner();
   4351   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
   4352     builder->Bailout(kArgumentsObjectValueInATestContext);
   4353   }
   4354   ToBooleanStub::Types expected(condition()->to_boolean_types());
   4355   ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
   4356 }
   4357 
   4358 
   4359 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
   4360 #define CHECK_BAILOUT(call)                     \
   4361   do {                                          \
   4362     call;                                       \
   4363     if (HasStackOverflow()) return;             \
   4364   } while (false)
   4365 
   4366 
   4367 #define CHECK_ALIVE(call)                                       \
   4368   do {                                                          \
   4369     call;                                                       \
   4370     if (HasStackOverflow() || current_block() == NULL) return;  \
   4371   } while (false)
   4372 
   4373 
   4374 #define CHECK_ALIVE_OR_RETURN(call, value)                            \
   4375   do {                                                                \
   4376     call;                                                             \
   4377     if (HasStackOverflow() || current_block() == NULL) return value;  \
   4378   } while (false)
   4379 
   4380 
   4381 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
   4382   current_info()->AbortOptimization(reason);
   4383   SetStackOverflow();
   4384 }
   4385 
   4386 
   4387 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
   4388   EffectContext for_effect(this);
   4389   Visit(expr);
   4390 }
   4391 
   4392 
   4393 void HOptimizedGraphBuilder::VisitForValue(Expression* expr,
   4394                                            ArgumentsAllowedFlag flag) {
   4395   ValueContext for_value(this, flag);
   4396   Visit(expr);
   4397 }
   4398 
   4399 
   4400 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) {
   4401   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
   4402   for_value.set_typeof_mode(INSIDE_TYPEOF);
   4403   Visit(expr);
   4404 }
   4405 
   4406 
   4407 void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
   4408                                              HBasicBlock* true_block,
   4409                                              HBasicBlock* false_block) {
   4410   TestContext for_control(this, expr, true_block, false_block);
   4411   Visit(expr);
   4412 }
   4413 
   4414 
   4415 void HOptimizedGraphBuilder::VisitExpressions(
   4416     ZoneList<Expression*>* exprs) {
   4417   for (int i = 0; i < exprs->length(); ++i) {
   4418     CHECK_ALIVE(VisitForValue(exprs->at(i)));
   4419   }
   4420 }
   4421 
   4422 
   4423 void HOptimizedGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs,
   4424                                               ArgumentsAllowedFlag flag) {
   4425   for (int i = 0; i < exprs->length(); ++i) {
   4426     CHECK_ALIVE(VisitForValue(exprs->at(i), flag));
   4427   }
   4428 }
   4429 
   4430 
   4431 bool HOptimizedGraphBuilder::BuildGraph() {
   4432   if (IsSubclassConstructor(current_info()->literal()->kind())) {
   4433     Bailout(kSuperReference);
   4434     return false;
   4435   }
   4436 
   4437   Scope* scope = current_info()->scope();
   4438   SetUpScope(scope);
   4439 
   4440   // Add an edge to the body entry.  This is warty: the graph's start
   4441   // environment will be used by the Lithium translation as the initial
   4442   // environment on graph entry, but it has now been mutated by the
   4443   // Hydrogen translation of the instructions in the start block.  This
   4444   // environment uses values which have not been defined yet.  These
   4445   // Hydrogen instructions will then be replayed by the Lithium
   4446   // translation, so they cannot have an environment effect.  The edge to
   4447   // the body's entry block (along with some special logic for the start
   4448   // block in HInstruction::InsertAfter) seals the start block from
   4449   // getting unwanted instructions inserted.
   4450   //
   4451   // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
   4452   // Make the Hydrogen instructions in the initial block into Hydrogen
   4453   // values (but not instructions), present in the initial environment and
   4454   // not replayed by the Lithium translation.
   4455   HEnvironment* initial_env = environment()->CopyWithoutHistory();
   4456   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
   4457   Goto(body_entry);
   4458   body_entry->SetJoinId(BailoutId::FunctionEntry());
   4459   set_current_block(body_entry);
   4460 
   4461   VisitDeclarations(scope->declarations());
   4462   Add<HSimulate>(BailoutId::Declarations());
   4463 
   4464   Add<HStackCheck>(HStackCheck::kFunctionEntry);
   4465 
   4466   VisitStatements(current_info()->literal()->body());
   4467   if (HasStackOverflow()) return false;
   4468 
   4469   if (current_block() != NULL) {
   4470     Add<HReturn>(graph()->GetConstantUndefined());
   4471     set_current_block(NULL);
   4472   }
   4473 
   4474   // If the checksum of the number of type info changes is the same as the
   4475   // last time this function was compiled, then this recompile is likely not
   4476   // due to missing/inadequate type feedback, but rather too aggressive
   4477   // optimization. Disable optimistic LICM in that case.
   4478   Handle<Code> unoptimized_code(current_info()->shared_info()->code());
   4479   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
   4480   Handle<TypeFeedbackInfo> type_info(
   4481       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
   4482   int checksum = type_info->own_type_change_checksum();
   4483   int composite_checksum = graph()->update_type_change_checksum(checksum);
   4484   graph()->set_use_optimistic_licm(
   4485       !type_info->matches_inlined_type_change_checksum(composite_checksum));
   4486   type_info->set_inlined_type_change_checksum(composite_checksum);
   4487 
   4488   // Perform any necessary OSR-specific cleanups or changes to the graph.
   4489   osr()->FinishGraph();
   4490 
   4491   return true;
   4492 }
   4493 
   4494 
   4495 bool HGraph::Optimize(BailoutReason* bailout_reason) {
   4496   OrderBlocks();
   4497   AssignDominators();
   4498 
   4499   // We need to create a HConstant "zero" now so that GVN will fold every
   4500   // zero-valued constant in the graph together.
   4501   // The constant is needed to make idef-based bounds check work: the pass
   4502   // evaluates relations with "zero" and that zero cannot be created after GVN.
   4503   GetConstant0();
   4504 
   4505 #ifdef DEBUG
   4506   // Do a full verify after building the graph and computing dominators.
   4507   Verify(true);
   4508 #endif
   4509 
   4510   if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
   4511     Run<HEnvironmentLivenessAnalysisPhase>();
   4512   }
   4513 
   4514   if (!CheckConstPhiUses()) {
   4515     *bailout_reason = kUnsupportedPhiUseOfConstVariable;
   4516     return false;
   4517   }
   4518   Run<HRedundantPhiEliminationPhase>();
   4519   if (!CheckArgumentsPhiUses()) {
   4520     *bailout_reason = kUnsupportedPhiUseOfArguments;
   4521     return false;
   4522   }
   4523 
   4524   // Find and mark unreachable code to simplify optimizations, especially gvn,
   4525   // where unreachable code could unnecessarily defeat LICM.
   4526   Run<HMarkUnreachableBlocksPhase>();
   4527 
   4528   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
   4529   if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
   4530 
   4531   if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
   4532 
   4533   CollectPhis();
   4534 
   4535   if (has_osr()) osr()->FinishOsrValues();
   4536 
   4537   Run<HInferRepresentationPhase>();
   4538 
   4539   // Remove HSimulate instructions that have turned out not to be needed
   4540   // after all by folding them into the following HSimulate.
   4541   // This must happen after inferring representations.
   4542   Run<HMergeRemovableSimulatesPhase>();
   4543 
   4544   Run<HMarkDeoptimizeOnUndefinedPhase>();
   4545   Run<HRepresentationChangesPhase>();
   4546 
   4547   Run<HInferTypesPhase>();
   4548 
   4549   // Must be performed before canonicalization to ensure that Canonicalize
   4550   // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
   4551   // zero.
   4552   Run<HUint32AnalysisPhase>();
   4553 
   4554   if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
   4555 
   4556   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
   4557 
   4558   if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
   4559 
   4560   if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
   4561 
   4562   Run<HRangeAnalysisPhase>();
   4563 
   4564   Run<HComputeChangeUndefinedToNaN>();
   4565 
   4566   // Eliminate redundant stack checks on backwards branches.
   4567   Run<HStackCheckEliminationPhase>();
   4568 
   4569   if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
   4570   if (FLAG_array_bounds_checks_hoisting) Run<HBoundsCheckHoistingPhase>();
   4571   if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
   4572   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
   4573 
   4574   RestoreActualValues();
   4575 
   4576   // Find unreachable code a second time, GVN and other optimizations may have
   4577   // made blocks unreachable that were previously reachable.
   4578   Run<HMarkUnreachableBlocksPhase>();
   4579 
   4580   return true;
   4581 }
   4582 
   4583 
   4584 void HGraph::RestoreActualValues() {
   4585   HPhase phase("H_Restore actual values", this);
   4586 
   4587   for (int block_index = 0; block_index < blocks()->length(); block_index++) {
   4588     HBasicBlock* block = blocks()->at(block_index);
   4589 
   4590 #ifdef DEBUG
   4591     for (int i = 0; i < block->phis()->length(); i++) {
   4592       HPhi* phi = block->phis()->at(i);
   4593       DCHECK(phi->ActualValue() == phi);
   4594     }
   4595 #endif
   4596 
   4597     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
   4598       HInstruction* instruction = it.Current();
   4599       if (instruction->ActualValue() == instruction) continue;
   4600       if (instruction->CheckFlag(HValue::kIsDead)) {
   4601         // The instruction was marked as deleted but left in the graph
   4602         // as a control flow dependency point for subsequent
   4603         // instructions.
   4604         instruction->DeleteAndReplaceWith(instruction->ActualValue());
   4605       } else {
   4606         DCHECK(instruction->IsInformativeDefinition());
   4607         if (instruction->IsPurelyInformativeDefinition()) {
   4608           instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
   4609         } else {
   4610           instruction->ReplaceAllUsesWith(instruction->ActualValue());
   4611         }
   4612       }
   4613     }
   4614   }
   4615 }
   4616 
   4617 
   4618 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
   4619   ZoneList<HValue*> arguments(count, zone());
   4620   for (int i = 0; i < count; ++i) {
   4621     arguments.Add(Pop(), zone());
   4622   }
   4623 
   4624   HPushArguments* push_args = New<HPushArguments>();
   4625   while (!arguments.is_empty()) {
   4626     push_args->AddInput(arguments.RemoveLast());
   4627   }
   4628   AddInstruction(push_args);
   4629 }
   4630 
   4631 
   4632 template <class Instruction>
   4633 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
   4634   PushArgumentsFromEnvironment(call->argument_count());
   4635   return call;
   4636 }
   4637 
   4638 
   4639 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) {
   4640   HEnvironment* prolog_env = environment();
   4641   int parameter_count = environment()->parameter_count();
   4642   ZoneList<HValue*> parameters(parameter_count, zone());
   4643   for (int i = 0; i < parameter_count; ++i) {
   4644     HInstruction* parameter = Add<HParameter>(static_cast<unsigned>(i));
   4645     parameters.Add(parameter, zone());
   4646     environment()->Bind(i, parameter);
   4647   }
   4648 
   4649   HConstant* undefined_constant = graph()->GetConstantUndefined();
   4650   // Initialize specials and locals to undefined.
   4651   for (int i = parameter_count + 1; i < environment()->length(); ++i) {
   4652     environment()->Bind(i, undefined_constant);
   4653   }
   4654   Add<HPrologue>();
   4655 
   4656   HEnvironment* initial_env = environment()->CopyWithoutHistory();
   4657   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
   4658   GotoNoSimulate(body_entry);
   4659   set_current_block(body_entry);
   4660 
   4661   // Initialize context of prolog environment to undefined.
   4662   prolog_env->BindContext(undefined_constant);
   4663 
   4664   // First special is HContext.
   4665   HInstruction* context = Add<HContext>();
   4666   environment()->BindContext(context);
   4667 
   4668   // Create an arguments object containing the initial parameters.  Set the
   4669   // initial values of parameters including "this" having parameter index 0.
   4670   DCHECK_EQ(scope->num_parameters() + 1, parameter_count);
   4671   HArgumentsObject* arguments_object = New<HArgumentsObject>(parameter_count);
   4672   for (int i = 0; i < parameter_count; ++i) {
   4673     HValue* parameter = parameters.at(i);
   4674     arguments_object->AddArgument(parameter, zone());
   4675   }
   4676 
   4677   AddInstruction(arguments_object);
   4678   graph()->SetArgumentsObject(arguments_object);
   4679 
   4680   // Handle the arguments and arguments shadow variables specially (they do
   4681   // not have declarations).
   4682   if (scope->arguments() != NULL) {
   4683     environment()->Bind(scope->arguments(), graph()->GetArgumentsObject());
   4684   }
   4685 
   4686   int rest_index;
   4687   Variable* rest = scope->rest_parameter(&rest_index);
   4688   if (rest) {
   4689     return Bailout(kRestParameter);
   4690   }
   4691 
   4692   if (scope->this_function_var() != nullptr ||
   4693       scope->new_target_var() != nullptr) {
   4694     return Bailout(kSuperReference);
   4695   }
   4696 
   4697   // Trace the call.
   4698   if (FLAG_trace && top_info()->IsOptimizing()) {
   4699     Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kTraceEnter), 0);
   4700   }
   4701 }
   4702 
   4703 
   4704 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
   4705   for (int i = 0; i < statements->length(); i++) {
   4706     Statement* stmt = statements->at(i);
   4707     CHECK_ALIVE(Visit(stmt));
   4708     if (stmt->IsJump()) break;
   4709   }
   4710 }
   4711 
   4712 
   4713 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
   4714   DCHECK(!HasStackOverflow());
   4715   DCHECK(current_block() != NULL);
   4716   DCHECK(current_block()->HasPredecessor());
   4717 
   4718   Scope* outer_scope = scope();
   4719   Scope* scope = stmt->scope();
   4720   BreakAndContinueInfo break_info(stmt, outer_scope);
   4721 
   4722   { BreakAndContinueScope push(&break_info, this);
   4723     if (scope != NULL) {
   4724       if (scope->NeedsContext()) {
   4725         // Load the function object.
   4726         Scope* declaration_scope = scope->DeclarationScope();
   4727         HInstruction* function;
   4728         HValue* outer_context = environment()->context();
   4729         if (declaration_scope->is_script_scope() ||
   4730             declaration_scope->is_eval_scope()) {
   4731           function = new (zone())
   4732               HLoadContextSlot(outer_context, Context::CLOSURE_INDEX,
   4733                                HLoadContextSlot::kNoCheck);
   4734         } else {
   4735           function = New<HThisFunction>();
   4736         }
   4737         AddInstruction(function);
   4738         // Allocate a block context and store it to the stack frame.
   4739         HInstruction* inner_context = Add<HAllocateBlockContext>(
   4740             outer_context, function, scope->GetScopeInfo(isolate()));
   4741         HInstruction* instr = Add<HStoreFrameContext>(inner_context);
   4742         set_scope(scope);
   4743         environment()->BindContext(inner_context);
   4744         if (instr->HasObservableSideEffects()) {
   4745           AddSimulate(stmt->EntryId(), REMOVABLE_SIMULATE);
   4746         }
   4747       }
   4748       VisitDeclarations(scope->declarations());
   4749       AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
   4750     }
   4751     CHECK_BAILOUT(VisitStatements(stmt->statements()));
   4752   }
   4753   set_scope(outer_scope);
   4754   if (scope != NULL && current_block() != NULL &&
   4755       scope->ContextLocalCount() > 0) {
   4756     HValue* inner_context = environment()->context();
   4757     HValue* outer_context = Add<HLoadNamedField>(
   4758         inner_context, nullptr,
   4759         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4760 
   4761     HInstruction* instr = Add<HStoreFrameContext>(outer_context);
   4762     environment()->BindContext(outer_context);
   4763     if (instr->HasObservableSideEffects()) {
   4764       AddSimulate(stmt->ExitId(), REMOVABLE_SIMULATE);
   4765     }
   4766   }
   4767   HBasicBlock* break_block = break_info.break_block();
   4768   if (break_block != NULL) {
   4769     if (current_block() != NULL) Goto(break_block);
   4770     break_block->SetJoinId(stmt->ExitId());
   4771     set_current_block(break_block);
   4772   }
   4773 }
   4774 
   4775 
   4776 void HOptimizedGraphBuilder::VisitExpressionStatement(
   4777     ExpressionStatement* stmt) {
   4778   DCHECK(!HasStackOverflow());
   4779   DCHECK(current_block() != NULL);
   4780   DCHECK(current_block()->HasPredecessor());
   4781   VisitForEffect(stmt->expression());
   4782 }
   4783 
   4784 
   4785 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
   4786   DCHECK(!HasStackOverflow());
   4787   DCHECK(current_block() != NULL);
   4788   DCHECK(current_block()->HasPredecessor());
   4789 }
   4790 
   4791 
   4792 void HOptimizedGraphBuilder::VisitSloppyBlockFunctionStatement(
   4793     SloppyBlockFunctionStatement* stmt) {
   4794   Visit(stmt->statement());
   4795 }
   4796 
   4797 
   4798 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
   4799   DCHECK(!HasStackOverflow());
   4800   DCHECK(current_block() != NULL);
   4801   DCHECK(current_block()->HasPredecessor());
   4802   if (stmt->condition()->ToBooleanIsTrue()) {
   4803     Add<HSimulate>(stmt->ThenId());
   4804     Visit(stmt->then_statement());
   4805   } else if (stmt->condition()->ToBooleanIsFalse()) {
   4806     Add<HSimulate>(stmt->ElseId());
   4807     Visit(stmt->else_statement());
   4808   } else {
   4809     HBasicBlock* cond_true = graph()->CreateBasicBlock();
   4810     HBasicBlock* cond_false = graph()->CreateBasicBlock();
   4811     CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
   4812 
   4813     if (cond_true->HasPredecessor()) {
   4814       cond_true->SetJoinId(stmt->ThenId());
   4815       set_current_block(cond_true);
   4816       CHECK_BAILOUT(Visit(stmt->then_statement()));
   4817       cond_true = current_block();
   4818     } else {
   4819       cond_true = NULL;
   4820     }
   4821 
   4822     if (cond_false->HasPredecessor()) {
   4823       cond_false->SetJoinId(stmt->ElseId());
   4824       set_current_block(cond_false);
   4825       CHECK_BAILOUT(Visit(stmt->else_statement()));
   4826       cond_false = current_block();
   4827     } else {
   4828       cond_false = NULL;
   4829     }
   4830 
   4831     HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
   4832     set_current_block(join);
   4833   }
   4834 }
   4835 
   4836 
   4837 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
   4838     BreakableStatement* stmt,
   4839     BreakType type,
   4840     Scope** scope,
   4841     int* drop_extra) {
   4842   *drop_extra = 0;
   4843   BreakAndContinueScope* current = this;
   4844   while (current != NULL && current->info()->target() != stmt) {
   4845     *drop_extra += current->info()->drop_extra();
   4846     current = current->next();
   4847   }
   4848   DCHECK(current != NULL);  // Always found (unless stack is malformed).
   4849   *scope = current->info()->scope();
   4850 
   4851   if (type == BREAK) {
   4852     *drop_extra += current->info()->drop_extra();
   4853   }
   4854 
   4855   HBasicBlock* block = NULL;
   4856   switch (type) {
   4857     case BREAK:
   4858       block = current->info()->break_block();
   4859       if (block == NULL) {
   4860         block = current->owner()->graph()->CreateBasicBlock();
   4861         current->info()->set_break_block(block);
   4862       }
   4863       break;
   4864 
   4865     case CONTINUE:
   4866       block = current->info()->continue_block();
   4867       if (block == NULL) {
   4868         block = current->owner()->graph()->CreateBasicBlock();
   4869         current->info()->set_continue_block(block);
   4870       }
   4871       break;
   4872   }
   4873 
   4874   return block;
   4875 }
   4876 
   4877 
   4878 void HOptimizedGraphBuilder::VisitContinueStatement(
   4879     ContinueStatement* stmt) {
   4880   DCHECK(!HasStackOverflow());
   4881   DCHECK(current_block() != NULL);
   4882   DCHECK(current_block()->HasPredecessor());
   4883   Scope* outer_scope = NULL;
   4884   Scope* inner_scope = scope();
   4885   int drop_extra = 0;
   4886   HBasicBlock* continue_block = break_scope()->Get(
   4887       stmt->target(), BreakAndContinueScope::CONTINUE,
   4888       &outer_scope, &drop_extra);
   4889   HValue* context = environment()->context();
   4890   Drop(drop_extra);
   4891   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
   4892   if (context_pop_count > 0) {
   4893     while (context_pop_count-- > 0) {
   4894       HInstruction* context_instruction = Add<HLoadNamedField>(
   4895           context, nullptr,
   4896           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4897       context = context_instruction;
   4898     }
   4899     HInstruction* instr = Add<HStoreFrameContext>(context);
   4900     if (instr->HasObservableSideEffects()) {
   4901       AddSimulate(stmt->target()->EntryId(), REMOVABLE_SIMULATE);
   4902     }
   4903     environment()->BindContext(context);
   4904   }
   4905 
   4906   Goto(continue_block);
   4907   set_current_block(NULL);
   4908 }
   4909 
   4910 
   4911 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
   4912   DCHECK(!HasStackOverflow());
   4913   DCHECK(current_block() != NULL);
   4914   DCHECK(current_block()->HasPredecessor());
   4915   Scope* outer_scope = NULL;
   4916   Scope* inner_scope = scope();
   4917   int drop_extra = 0;
   4918   HBasicBlock* break_block = break_scope()->Get(
   4919       stmt->target(), BreakAndContinueScope::BREAK,
   4920       &outer_scope, &drop_extra);
   4921   HValue* context = environment()->context();
   4922   Drop(drop_extra);
   4923   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
   4924   if (context_pop_count > 0) {
   4925     while (context_pop_count-- > 0) {
   4926       HInstruction* context_instruction = Add<HLoadNamedField>(
   4927           context, nullptr,
   4928           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4929       context = context_instruction;
   4930     }
   4931     HInstruction* instr = Add<HStoreFrameContext>(context);
   4932     if (instr->HasObservableSideEffects()) {
   4933       AddSimulate(stmt->target()->ExitId(), REMOVABLE_SIMULATE);
   4934     }
   4935     environment()->BindContext(context);
   4936   }
   4937   Goto(break_block);
   4938   set_current_block(NULL);
   4939 }
   4940 
   4941 
   4942 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
   4943   DCHECK(!HasStackOverflow());
   4944   DCHECK(current_block() != NULL);
   4945   DCHECK(current_block()->HasPredecessor());
   4946   FunctionState* state = function_state();
   4947   AstContext* context = call_context();
   4948   if (context == NULL) {
   4949     // Not an inlined return, so an actual one.
   4950     CHECK_ALIVE(VisitForValue(stmt->expression()));
   4951     HValue* result = environment()->Pop();
   4952     Add<HReturn>(result);
   4953   } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
   4954     // Return from an inlined construct call. In a test context the return value
   4955     // will always evaluate to true, in a value context the return value needs
   4956     // to be a JSObject.
   4957     if (context->IsTest()) {
   4958       TestContext* test = TestContext::cast(context);
   4959       CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4960       Goto(test->if_true(), state);
   4961     } else if (context->IsEffect()) {
   4962       CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4963       Goto(function_return(), state);
   4964     } else {
   4965       DCHECK(context->IsValue());
   4966       CHECK_ALIVE(VisitForValue(stmt->expression()));
   4967       HValue* return_value = Pop();
   4968       HValue* receiver = environment()->arguments_environment()->Lookup(0);
   4969       HHasInstanceTypeAndBranch* typecheck =
   4970           New<HHasInstanceTypeAndBranch>(return_value,
   4971                                          FIRST_JS_RECEIVER_TYPE,
   4972                                          LAST_JS_RECEIVER_TYPE);
   4973       HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
   4974       HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
   4975       typecheck->SetSuccessorAt(0, if_spec_object);
   4976       typecheck->SetSuccessorAt(1, not_spec_object);
   4977       FinishCurrentBlock(typecheck);
   4978       AddLeaveInlined(if_spec_object, return_value, state);
   4979       AddLeaveInlined(not_spec_object, receiver, state);
   4980     }
   4981   } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
   4982     // Return from an inlined setter call. The returned value is never used, the
   4983     // value of an assignment is always the value of the RHS of the assignment.
   4984     CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4985     if (context->IsTest()) {
   4986       HValue* rhs = environment()->arguments_environment()->Lookup(1);
   4987       context->ReturnValue(rhs);
   4988     } else if (context->IsEffect()) {
   4989       Goto(function_return(), state);
   4990     } else {
   4991       DCHECK(context->IsValue());
   4992       HValue* rhs = environment()->arguments_environment()->Lookup(1);
   4993       AddLeaveInlined(rhs, state);
   4994     }
   4995   } else {
   4996     // Return from a normal inlined function. Visit the subexpression in the
   4997     // expression context of the call.
   4998     if (context->IsTest()) {
   4999       TestContext* test = TestContext::cast(context);
   5000       VisitForControl(stmt->expression(), test->if_true(), test->if_false());
   5001     } else if (context->IsEffect()) {
   5002       // Visit in value context and ignore the result. This is needed to keep
   5003       // environment in sync with full-codegen since some visitors (e.g.
   5004       // VisitCountOperation) use the operand stack differently depending on
   5005       // context.
   5006       CHECK_ALIVE(VisitForValue(stmt->expression()));
   5007       Pop();
   5008       Goto(function_return(), state);
   5009     } else {
   5010       DCHECK(context->IsValue());
   5011       CHECK_ALIVE(VisitForValue(stmt->expression()));
   5012       AddLeaveInlined(Pop(), state);
   5013     }
   5014   }
   5015   set_current_block(NULL);
   5016 }
   5017 
   5018 
   5019 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
   5020   DCHECK(!HasStackOverflow());
   5021   DCHECK(current_block() != NULL);
   5022   DCHECK(current_block()->HasPredecessor());
   5023   return Bailout(kWithStatement);
   5024 }
   5025 
   5026 
   5027 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
   5028   DCHECK(!HasStackOverflow());
   5029   DCHECK(current_block() != NULL);
   5030   DCHECK(current_block()->HasPredecessor());
   5031 
   5032   ZoneList<CaseClause*>* clauses = stmt->cases();
   5033   int clause_count = clauses->length();
   5034   ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
   5035 
   5036   CHECK_ALIVE(VisitForValue(stmt->tag()));
   5037   Add<HSimulate>(stmt->EntryId());
   5038   HValue* tag_value = Top();
   5039   Type* tag_type = stmt->tag()->bounds().lower;
   5040 
   5041   // 1. Build all the tests, with dangling true branches
   5042   BailoutId default_id = BailoutId::None();
   5043   for (int i = 0; i < clause_count; ++i) {
   5044     CaseClause* clause = clauses->at(i);
   5045     if (clause->is_default()) {
   5046       body_blocks.Add(NULL, zone());
   5047       if (default_id.IsNone()) default_id = clause->EntryId();
   5048       continue;
   5049     }
   5050 
   5051     // Generate a compare and branch.
   5052     CHECK_BAILOUT(VisitForValue(clause->label()));
   5053     if (current_block() == NULL) return Bailout(kUnsupportedSwitchStatement);
   5054     HValue* label_value = Pop();
   5055 
   5056     Type* label_type = clause->label()->bounds().lower;
   5057     Type* combined_type = clause->compare_type();
   5058     HControlInstruction* compare = BuildCompareInstruction(
   5059         Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
   5060         combined_type,
   5061         ScriptPositionToSourcePosition(stmt->tag()->position()),
   5062         ScriptPositionToSourcePosition(clause->label()->position()),
   5063         PUSH_BEFORE_SIMULATE, clause->id());
   5064 
   5065     HBasicBlock* next_test_block = graph()->CreateBasicBlock();
   5066     HBasicBlock* body_block = graph()->CreateBasicBlock();
   5067     body_blocks.Add(body_block, zone());
   5068     compare->SetSuccessorAt(0, body_block);
   5069     compare->SetSuccessorAt(1, next_test_block);
   5070     FinishCurrentBlock(compare);
   5071 
   5072     set_current_block(body_block);
   5073     Drop(1);  // tag_value
   5074 
   5075     set_current_block(next_test_block);
   5076   }
   5077 
   5078   // Save the current block to use for the default or to join with the
   5079   // exit.
   5080   HBasicBlock* last_block = current_block();
   5081   Drop(1);  // tag_value
   5082 
   5083   // 2. Loop over the clauses and the linked list of tests in lockstep,
   5084   // translating the clause bodies.
   5085   HBasicBlock* fall_through_block = NULL;
   5086 
   5087   BreakAndContinueInfo break_info(stmt, scope());
   5088   { BreakAndContinueScope push(&break_info, this);
   5089     for (int i = 0; i < clause_count; ++i) {
   5090       CaseClause* clause = clauses->at(i);
   5091 
   5092       // Identify the block where normal (non-fall-through) control flow
   5093       // goes to.
   5094       HBasicBlock* normal_block = NULL;
   5095       if (clause->is_default()) {
   5096         if (last_block == NULL) continue;
   5097         normal_block = last_block;
   5098         last_block = NULL;  // Cleared to indicate we've handled it.
   5099       } else {
   5100         normal_block = body_blocks[i];
   5101       }
   5102 
   5103       if (fall_through_block == NULL) {
   5104         set_current_block(normal_block);
   5105       } else {
   5106         HBasicBlock* join = CreateJoin(fall_through_block,
   5107                                        normal_block,
   5108                                        clause->EntryId());
   5109         set_current_block(join);
   5110       }
   5111 
   5112       CHECK_BAILOUT(VisitStatements(clause->statements()));
   5113       fall_through_block = current_block();
   5114     }
   5115   }
   5116 
   5117   // Create an up-to-3-way join.  Use the break block if it exists since
   5118   // it's already a join block.
   5119   HBasicBlock* break_block = break_info.break_block();
   5120   if (break_block == NULL) {
   5121     set_current_block(CreateJoin(fall_through_block,
   5122                                  last_block,
   5123                                  stmt->ExitId()));
   5124   } else {
   5125     if (fall_through_block != NULL) Goto(fall_through_block, break_block);
   5126     if (last_block != NULL) Goto(last_block, break_block);
   5127     break_block->SetJoinId(stmt->ExitId());
   5128     set_current_block(break_block);
   5129   }
   5130 }
   5131 
   5132 
   5133 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
   5134                                            HBasicBlock* loop_entry) {
   5135   Add<HSimulate>(stmt->StackCheckId());
   5136   HStackCheck* stack_check =
   5137       HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
   5138   DCHECK(loop_entry->IsLoopHeader());
   5139   loop_entry->loop_information()->set_stack_check(stack_check);
   5140   CHECK_BAILOUT(Visit(stmt->body()));
   5141 }
   5142 
   5143 
   5144 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
   5145   DCHECK(!HasStackOverflow());
   5146   DCHECK(current_block() != NULL);
   5147   DCHECK(current_block()->HasPredecessor());
   5148   DCHECK(current_block() != NULL);
   5149   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   5150 
   5151   BreakAndContinueInfo break_info(stmt, scope());
   5152   {
   5153     BreakAndContinueScope push(&break_info, this);
   5154     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
   5155   }
   5156   HBasicBlock* body_exit =
   5157       JoinContinue(stmt, current_block(), break_info.continue_block());
   5158   HBasicBlock* loop_successor = NULL;
   5159   if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
   5160     set_current_block(body_exit);
   5161     loop_successor = graph()->CreateBasicBlock();
   5162     if (stmt->cond()->ToBooleanIsFalse()) {
   5163       loop_entry->loop_information()->stack_check()->Eliminate();
   5164       Goto(loop_successor);
   5165       body_exit = NULL;
   5166     } else {
   5167       // The block for a true condition, the actual predecessor block of the
   5168       // back edge.
   5169       body_exit = graph()->CreateBasicBlock();
   5170       CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
   5171     }
   5172     if (body_exit != NULL && body_exit->HasPredecessor()) {
   5173       body_exit->SetJoinId(stmt->BackEdgeId());
   5174     } else {
   5175       body_exit = NULL;
   5176     }
   5177     if (loop_successor->HasPredecessor()) {
   5178       loop_successor->SetJoinId(stmt->ExitId());
   5179     } else {
   5180       loop_successor = NULL;
   5181     }
   5182   }
   5183   HBasicBlock* loop_exit = CreateLoop(stmt,
   5184                                       loop_entry,
   5185                                       body_exit,
   5186                                       loop_successor,
   5187                                       break_info.break_block());
   5188   set_current_block(loop_exit);
   5189 }
   5190 
   5191 
   5192 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
   5193   DCHECK(!HasStackOverflow());
   5194   DCHECK(current_block() != NULL);
   5195   DCHECK(current_block()->HasPredecessor());
   5196   DCHECK(current_block() != NULL);
   5197   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   5198 
   5199   // If the condition is constant true, do not generate a branch.
   5200   HBasicBlock* loop_successor = NULL;
   5201   if (!stmt->cond()->ToBooleanIsTrue()) {
   5202     HBasicBlock* body_entry = graph()->CreateBasicBlock();
   5203     loop_successor = graph()->CreateBasicBlock();
   5204     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
   5205     if (body_entry->HasPredecessor()) {
   5206       body_entry->SetJoinId(stmt->BodyId());
   5207       set_current_block(body_entry);
   5208     }
   5209     if (loop_successor->HasPredecessor()) {
   5210       loop_successor->SetJoinId(stmt->ExitId());
   5211     } else {
   5212       loop_successor = NULL;
   5213     }
   5214   }
   5215 
   5216   BreakAndContinueInfo break_info(stmt, scope());
   5217   if (current_block() != NULL) {
   5218     BreakAndContinueScope push(&break_info, this);
   5219     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
   5220   }
   5221   HBasicBlock* body_exit =
   5222       JoinContinue(stmt, current_block(), break_info.continue_block());
   5223   HBasicBlock* loop_exit = CreateLoop(stmt,
   5224                                       loop_entry,
   5225                                       body_exit,
   5226                                       loop_successor,
   5227                                       break_info.break_block());
   5228   set_current_block(loop_exit);
   5229 }
   5230 
   5231 
   5232 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
   5233   DCHECK(!HasStackOverflow());
   5234   DCHECK(current_block() != NULL);
   5235   DCHECK(current_block()->HasPredecessor());
   5236   if (stmt->init() != NULL) {
   5237     CHECK_ALIVE(Visit(stmt->init()));
   5238   }
   5239   DCHECK(current_block() != NULL);
   5240   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   5241 
   5242   HBasicBlock* loop_successor = NULL;
   5243   if (stmt->cond() != NULL) {
   5244     HBasicBlock* body_entry = graph()->CreateBasicBlock();
   5245     loop_successor = graph()->CreateBasicBlock();
   5246     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
   5247     if (body_entry->HasPredecessor()) {
   5248       body_entry->SetJoinId(stmt->BodyId());
   5249       set_current_block(body_entry);
   5250     }
   5251     if (loop_successor->HasPredecessor()) {
   5252       loop_successor->SetJoinId(stmt->ExitId());
   5253     } else {
   5254       loop_successor = NULL;
   5255     }
   5256   }
   5257 
   5258   BreakAndContinueInfo break_info(stmt, scope());
   5259   if (current_block() != NULL) {
   5260     BreakAndContinueScope push(&break_info, this);
   5261     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
   5262   }
   5263   HBasicBlock* body_exit =
   5264       JoinContinue(stmt, current_block(), break_info.continue_block());
   5265 
   5266   if (stmt->next() != NULL && body_exit != NULL) {
   5267     set_current_block(body_exit);
   5268     CHECK_BAILOUT(Visit(stmt->next()));
   5269     body_exit = current_block();
   5270   }
   5271 
   5272   HBasicBlock* loop_exit = CreateLoop(stmt,
   5273                                       loop_entry,
   5274                                       body_exit,
   5275                                       loop_successor,
   5276                                       break_info.break_block());
   5277   set_current_block(loop_exit);
   5278 }
   5279 
   5280 
   5281 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
   5282   DCHECK(!HasStackOverflow());
   5283   DCHECK(current_block() != NULL);
   5284   DCHECK(current_block()->HasPredecessor());
   5285 
   5286   if (!FLAG_optimize_for_in) {
   5287     return Bailout(kForInStatementOptimizationIsDisabled);
   5288   }
   5289 
   5290   if (!stmt->each()->IsVariableProxy() ||
   5291       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
   5292     return Bailout(kForInStatementWithNonLocalEachVariable);
   5293   }
   5294 
   5295   Variable* each_var = stmt->each()->AsVariableProxy()->var();
   5296 
   5297   CHECK_ALIVE(VisitForValue(stmt->enumerable()));
   5298   HValue* enumerable = Top();  // Leave enumerable at the top.
   5299 
   5300   IfBuilder if_undefined_or_null(this);
   5301   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
   5302       enumerable, graph()->GetConstantUndefined());
   5303   if_undefined_or_null.Or();
   5304   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
   5305       enumerable, graph()->GetConstantNull());
   5306   if_undefined_or_null.ThenDeopt(Deoptimizer::kUndefinedOrNullInForIn);
   5307   if_undefined_or_null.End();
   5308   BuildForInBody(stmt, each_var, enumerable);
   5309 }
   5310 
   5311 
   5312 void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
   5313                                             Variable* each_var,
   5314                                             HValue* enumerable) {
   5315   HInstruction* map;
   5316   HInstruction* array;
   5317   HInstruction* enum_length;
   5318   bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN;
   5319   if (fast) {
   5320     map = Add<HForInPrepareMap>(enumerable);
   5321     Add<HSimulate>(stmt->PrepareId());
   5322 
   5323     array = Add<HForInCacheArray>(enumerable, map,
   5324                                   DescriptorArray::kEnumCacheBridgeCacheIndex);
   5325     enum_length = Add<HMapEnumLength>(map);
   5326 
   5327     HInstruction* index_cache = Add<HForInCacheArray>(
   5328         enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
   5329     HForInCacheArray::cast(array)
   5330         ->set_index_cache(HForInCacheArray::cast(index_cache));
   5331   } else {
   5332     Add<HSimulate>(stmt->PrepareId());
   5333     {
   5334       NoObservableSideEffectsScope no_effects(this);
   5335       BuildJSObjectCheck(enumerable, 0);
   5336     }
   5337     Add<HSimulate>(stmt->ToObjectId());
   5338 
   5339     map = graph()->GetConstant1();
   5340     Runtime::FunctionId function_id = Runtime::kGetPropertyNamesFast;
   5341     Add<HPushArguments>(enumerable);
   5342     array = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
   5343     Push(array);
   5344     Add<HSimulate>(stmt->EnumId());
   5345     Drop(1);
   5346     Handle<Map> array_map = isolate()->factory()->fixed_array_map();
   5347     HValue* check = Add<HCheckMaps>(array, array_map);
   5348     enum_length = AddLoadFixedArrayLength(array, check);
   5349   }
   5350 
   5351   HInstruction* start_index = Add<HConstant>(0);
   5352 
   5353   Push(map);
   5354   Push(array);
   5355   Push(enum_length);
   5356   Push(start_index);
   5357 
   5358   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   5359 
   5360   // Reload the values to ensure we have up-to-date values inside of the loop.
   5361   // This is relevant especially for OSR where the values don't come from the
   5362   // computation above, but from the OSR entry block.
   5363   enumerable = environment()->ExpressionStackAt(4);
   5364   HValue* index = environment()->ExpressionStackAt(0);
   5365   HValue* limit = environment()->ExpressionStackAt(1);
   5366 
   5367   // Check that we still have more keys.
   5368   HCompareNumericAndBranch* compare_index =
   5369       New<HCompareNumericAndBranch>(index, limit, Token::LT);
   5370   compare_index->set_observed_input_representation(
   5371       Representation::Smi(), Representation::Smi());
   5372 
   5373   HBasicBlock* loop_body = graph()->CreateBasicBlock();
   5374   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
   5375 
   5376   compare_index->SetSuccessorAt(0, loop_body);
   5377   compare_index->SetSuccessorAt(1, loop_successor);
   5378   FinishCurrentBlock(compare_index);
   5379 
   5380   set_current_block(loop_successor);
   5381   Drop(5);
   5382 
   5383   set_current_block(loop_body);
   5384 
   5385   HValue* key =
   5386       Add<HLoadKeyed>(environment()->ExpressionStackAt(2),  // Enum cache.
   5387                       index, index, nullptr, FAST_ELEMENTS);
   5388 
   5389   if (fast) {
   5390     // Check if the expected map still matches that of the enumerable.
   5391     // If not just deoptimize.
   5392     Add<HCheckMapValue>(enumerable, environment()->ExpressionStackAt(3));
   5393     Bind(each_var, key);
   5394   } else {
   5395     Add<HPushArguments>(enumerable, key);
   5396     Runtime::FunctionId function_id = Runtime::kForInFilter;
   5397     key = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
   5398     Push(key);
   5399     Add<HSimulate>(stmt->FilterId());
   5400     key = Pop();
   5401     Bind(each_var, key);
   5402     IfBuilder if_undefined(this);
   5403     if_undefined.If<HCompareObjectEqAndBranch>(key,
   5404                                                graph()->GetConstantUndefined());
   5405     if_undefined.ThenDeopt(Deoptimizer::kUndefined);
   5406     if_undefined.End();
   5407     Add<HSimulate>(stmt->AssignmentId());
   5408   }
   5409 
   5410   BreakAndContinueInfo break_info(stmt, scope(), 5);
   5411   {
   5412     BreakAndContinueScope push(&break_info, this);
   5413     CHECK_BAILOUT(VisitLoopBody(stmt, loop_entry));
   5414   }
   5415 
   5416   HBasicBlock* body_exit =
   5417       JoinContinue(stmt, current_block(), break_info.continue_block());
   5418 
   5419   if (body_exit != NULL) {
   5420     set_current_block(body_exit);
   5421 
   5422     HValue* current_index = Pop();
   5423     Push(AddUncasted<HAdd>(current_index, graph()->GetConstant1()));
   5424     body_exit = current_block();
   5425   }
   5426 
   5427   HBasicBlock* loop_exit = CreateLoop(stmt,
   5428                                       loop_entry,
   5429                                       body_exit,
   5430                                       loop_successor,
   5431                                       break_info.break_block());
   5432 
   5433   set_current_block(loop_exit);
   5434 }
   5435 
   5436 
   5437 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
   5438   DCHECK(!HasStackOverflow());
   5439   DCHECK(current_block() != NULL);
   5440   DCHECK(current_block()->HasPredecessor());
   5441   return Bailout(kForOfStatement);
   5442 }
   5443 
   5444 
   5445 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
   5446   DCHECK(!HasStackOverflow());
   5447   DCHECK(current_block() != NULL);
   5448   DCHECK(current_block()->HasPredecessor());
   5449   return Bailout(kTryCatchStatement);
   5450 }
   5451 
   5452 
   5453 void HOptimizedGraphBuilder::VisitTryFinallyStatement(
   5454     TryFinallyStatement* stmt) {
   5455   DCHECK(!HasStackOverflow());
   5456   DCHECK(current_block() != NULL);
   5457   DCHECK(current_block()->HasPredecessor());
   5458   return Bailout(kTryFinallyStatement);
   5459 }
   5460 
   5461 
   5462 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
   5463   DCHECK(!HasStackOverflow());
   5464   DCHECK(current_block() != NULL);
   5465   DCHECK(current_block()->HasPredecessor());
   5466   return Bailout(kDebuggerStatement);
   5467 }
   5468 
   5469 
   5470 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
   5471   UNREACHABLE();
   5472 }
   5473 
   5474 
   5475 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
   5476   DCHECK(!HasStackOverflow());
   5477   DCHECK(current_block() != NULL);
   5478   DCHECK(current_block()->HasPredecessor());
   5479   Handle<SharedFunctionInfo> shared_info = Compiler::GetSharedFunctionInfo(
   5480       expr, current_info()->script(), top_info());
   5481   // We also have a stack overflow if the recursive compilation did.
   5482   if (HasStackOverflow()) return;
   5483   // Use the fast case closure allocation code that allocates in new
   5484   // space for nested functions that don't need literals cloning.
   5485   HConstant* shared_info_value = Add<HConstant>(shared_info);
   5486   HInstruction* instr;
   5487   if (!expr->pretenure() && shared_info->num_literals() == 0) {
   5488     FastNewClosureStub stub(isolate(), shared_info->language_mode(),
   5489                             shared_info->kind());
   5490     FastNewClosureDescriptor descriptor(isolate());
   5491     HValue* values[] = {context(), shared_info_value};
   5492     HConstant* stub_value = Add<HConstant>(stub.GetCode());
   5493     instr = New<HCallWithDescriptor>(stub_value, 0, descriptor,
   5494                                      Vector<HValue*>(values, arraysize(values)),
   5495                                      NORMAL_CALL);
   5496   } else {
   5497     Add<HPushArguments>(shared_info_value);
   5498     Runtime::FunctionId function_id =
   5499         expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure;
   5500     instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
   5501   }
   5502   return ast_context()->ReturnInstruction(instr, expr->id());
   5503 }
   5504 
   5505 
   5506 void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
   5507   DCHECK(!HasStackOverflow());
   5508   DCHECK(current_block() != NULL);
   5509   DCHECK(current_block()->HasPredecessor());
   5510   return Bailout(kClassLiteral);
   5511 }
   5512 
   5513 
   5514 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
   5515     NativeFunctionLiteral* expr) {
   5516   DCHECK(!HasStackOverflow());
   5517   DCHECK(current_block() != NULL);
   5518   DCHECK(current_block()->HasPredecessor());
   5519   return Bailout(kNativeFunctionLiteral);
   5520 }
   5521 
   5522 
   5523 void HOptimizedGraphBuilder::VisitDoExpression(DoExpression* expr) {
   5524   DCHECK(!HasStackOverflow());
   5525   DCHECK(current_block() != NULL);
   5526   DCHECK(current_block()->HasPredecessor());
   5527   return Bailout(kDoExpression);
   5528 }
   5529 
   5530 
   5531 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
   5532   DCHECK(!HasStackOverflow());
   5533   DCHECK(current_block() != NULL);
   5534   DCHECK(current_block()->HasPredecessor());
   5535   HBasicBlock* cond_true = graph()->CreateBasicBlock();
   5536   HBasicBlock* cond_false = graph()->CreateBasicBlock();
   5537   CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
   5538 
   5539   // Visit the true and false subexpressions in the same AST context as the
   5540   // whole expression.
   5541   if (cond_true->HasPredecessor()) {
   5542     cond_true->SetJoinId(expr->ThenId());
   5543     set_current_block(cond_true);
   5544     CHECK_BAILOUT(Visit(expr->then_expression()));
   5545     cond_true = current_block();
   5546   } else {
   5547     cond_true = NULL;
   5548   }
   5549 
   5550   if (cond_false->HasPredecessor()) {
   5551     cond_false->SetJoinId(expr->ElseId());
   5552     set_current_block(cond_false);
   5553     CHECK_BAILOUT(Visit(expr->else_expression()));
   5554     cond_false = current_block();
   5555   } else {
   5556     cond_false = NULL;
   5557   }
   5558 
   5559   if (!ast_context()->IsTest()) {
   5560     HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
   5561     set_current_block(join);
   5562     if (join != NULL && !ast_context()->IsEffect()) {
   5563       return ast_context()->ReturnValue(Pop());
   5564     }
   5565   }
   5566 }
   5567 
   5568 
   5569 HOptimizedGraphBuilder::GlobalPropertyAccess
   5570 HOptimizedGraphBuilder::LookupGlobalProperty(Variable* var, LookupIterator* it,
   5571                                              PropertyAccessType access_type) {
   5572   if (var->is_this() || !current_info()->has_global_object()) {
   5573     return kUseGeneric;
   5574   }
   5575 
   5576   switch (it->state()) {
   5577     case LookupIterator::ACCESSOR:
   5578     case LookupIterator::ACCESS_CHECK:
   5579     case LookupIterator::INTERCEPTOR:
   5580     case LookupIterator::INTEGER_INDEXED_EXOTIC:
   5581     case LookupIterator::NOT_FOUND:
   5582       return kUseGeneric;
   5583     case LookupIterator::DATA:
   5584       if (access_type == STORE && it->IsReadOnly()) return kUseGeneric;
   5585       return kUseCell;
   5586     case LookupIterator::JSPROXY:
   5587     case LookupIterator::TRANSITION:
   5588       UNREACHABLE();
   5589   }
   5590   UNREACHABLE();
   5591   return kUseGeneric;
   5592 }
   5593 
   5594 
   5595 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
   5596   DCHECK(var->IsContextSlot());
   5597   HValue* context = environment()->context();
   5598   int length = scope()->ContextChainLength(var->scope());
   5599   while (length-- > 0) {
   5600     context = Add<HLoadNamedField>(
   5601         context, nullptr,
   5602         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   5603   }
   5604   return context;
   5605 }
   5606 
   5607 
   5608 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
   5609   DCHECK(!HasStackOverflow());
   5610   DCHECK(current_block() != NULL);
   5611   DCHECK(current_block()->HasPredecessor());
   5612   Variable* variable = expr->var();
   5613   switch (variable->location()) {
   5614     case VariableLocation::GLOBAL:
   5615     case VariableLocation::UNALLOCATED: {
   5616       if (IsLexicalVariableMode(variable->mode())) {
   5617         // TODO(rossberg): should this be an DCHECK?
   5618         return Bailout(kReferenceToGlobalLexicalVariable);
   5619       }
   5620       // Handle known global constants like 'undefined' specially to avoid a
   5621       // load from a global cell for them.
   5622       Handle<Object> constant_value =
   5623           isolate()->factory()->GlobalConstantFor(variable->name());
   5624       if (!constant_value.is_null()) {
   5625         HConstant* instr = New<HConstant>(constant_value);
   5626         return ast_context()->ReturnInstruction(instr, expr->id());
   5627       }
   5628 
   5629       Handle<JSGlobalObject> global(current_info()->global_object());
   5630 
   5631       // Lookup in script contexts.
   5632       {
   5633         Handle<ScriptContextTable> script_contexts(
   5634             global->native_context()->script_context_table());
   5635         ScriptContextTable::LookupResult lookup;
   5636         if (ScriptContextTable::Lookup(script_contexts, variable->name(),
   5637                                        &lookup)) {
   5638           Handle<Context> script_context = ScriptContextTable::GetContext(
   5639               script_contexts, lookup.context_index);
   5640           Handle<Object> current_value =
   5641               FixedArray::get(script_context, lookup.slot_index);
   5642 
   5643           // If the values is not the hole, it will stay initialized,
   5644           // so no need to generate a check.
   5645           if (*current_value == *isolate()->factory()->the_hole_value()) {
   5646             return Bailout(kReferenceToUninitializedVariable);
   5647           }
   5648           HInstruction* result = New<HLoadNamedField>(
   5649               Add<HConstant>(script_context), nullptr,
   5650               HObjectAccess::ForContextSlot(lookup.slot_index));
   5651           return ast_context()->ReturnInstruction(result, expr->id());
   5652         }
   5653       }
   5654 
   5655       LookupIterator it(global, variable->name(), LookupIterator::OWN);
   5656       GlobalPropertyAccess type = LookupGlobalProperty(variable, &it, LOAD);
   5657 
   5658       if (type == kUseCell) {
   5659         Handle<PropertyCell> cell = it.GetPropertyCell();
   5660         top_info()->dependencies()->AssumePropertyCell(cell);
   5661         auto cell_type = it.property_details().cell_type();
   5662         if (cell_type == PropertyCellType::kConstant ||
   5663             cell_type == PropertyCellType::kUndefined) {
   5664           Handle<Object> constant_object(cell->value(), isolate());
   5665           if (constant_object->IsConsString()) {
   5666             constant_object =
   5667                 String::Flatten(Handle<String>::cast(constant_object));
   5668           }
   5669           HConstant* constant = New<HConstant>(constant_object);
   5670           return ast_context()->ReturnInstruction(constant, expr->id());
   5671         } else {
   5672           auto access = HObjectAccess::ForPropertyCellValue();
   5673           UniqueSet<Map>* field_maps = nullptr;
   5674           if (cell_type == PropertyCellType::kConstantType) {
   5675             switch (cell->GetConstantType()) {
   5676               case PropertyCellConstantType::kSmi:
   5677                 access = access.WithRepresentation(Representation::Smi());
   5678                 break;
   5679               case PropertyCellConstantType::kStableMap: {
   5680                 // Check that the map really is stable. The heap object could
   5681                 // have mutated without the cell updating state. In that case,
   5682                 // make no promises about the loaded value except that it's a
   5683                 // heap object.
   5684                 access =
   5685                     access.WithRepresentation(Representation::HeapObject());
   5686                 Handle<Map> map(HeapObject::cast(cell->value())->map());
   5687                 if (map->is_stable()) {
   5688                   field_maps = new (zone())
   5689                       UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone());
   5690                 }
   5691                 break;
   5692               }
   5693             }
   5694           }
   5695           HConstant* cell_constant = Add<HConstant>(cell);
   5696           HLoadNamedField* instr;
   5697           if (field_maps == nullptr) {
   5698             instr = New<HLoadNamedField>(cell_constant, nullptr, access);
   5699           } else {
   5700             instr = New<HLoadNamedField>(cell_constant, nullptr, access,
   5701                                          field_maps, HType::HeapObject());
   5702           }
   5703           instr->ClearDependsOnFlag(kInobjectFields);
   5704           instr->SetDependsOnFlag(kGlobalVars);
   5705           return ast_context()->ReturnInstruction(instr, expr->id());
   5706         }
   5707       } else {
   5708         HValue* global_object = Add<HLoadNamedField>(
   5709             BuildGetNativeContext(), nullptr,
   5710             HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX));
   5711         HLoadGlobalGeneric* instr = New<HLoadGlobalGeneric>(
   5712             global_object, variable->name(), ast_context()->typeof_mode());
   5713         instr->SetVectorAndSlot(handle(current_feedback_vector(), isolate()),
   5714                                 expr->VariableFeedbackSlot());
   5715         return ast_context()->ReturnInstruction(instr, expr->id());
   5716       }
   5717     }
   5718 
   5719     case VariableLocation::PARAMETER:
   5720     case VariableLocation::LOCAL: {
   5721       HValue* value = LookupAndMakeLive(variable);
   5722       if (value == graph()->GetConstantHole()) {
   5723         DCHECK(IsDeclaredVariableMode(variable->mode()) &&
   5724                variable->mode() != VAR);
   5725         return Bailout(kReferenceToUninitializedVariable);
   5726       }
   5727       return ast_context()->ReturnValue(value);
   5728     }
   5729 
   5730     case VariableLocation::CONTEXT: {
   5731       HValue* context = BuildContextChainWalk(variable);
   5732       HLoadContextSlot::Mode mode;
   5733       switch (variable->mode()) {
   5734         case LET:
   5735         case CONST:
   5736           mode = HLoadContextSlot::kCheckDeoptimize;
   5737           break;
   5738         case CONST_LEGACY:
   5739           mode = HLoadContextSlot::kCheckReturnUndefined;
   5740           break;
   5741         default:
   5742           mode = HLoadContextSlot::kNoCheck;
   5743           break;
   5744       }
   5745       HLoadContextSlot* instr =
   5746           new(zone()) HLoadContextSlot(context, variable->index(), mode);
   5747       return ast_context()->ReturnInstruction(instr, expr->id());
   5748     }
   5749 
   5750     case VariableLocation::LOOKUP:
   5751       return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
   5752   }
   5753 }
   5754 
   5755 
   5756 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
   5757   DCHECK(!HasStackOverflow());
   5758   DCHECK(current_block() != NULL);
   5759   DCHECK(current_block()->HasPredecessor());
   5760   HConstant* instr = New<HConstant>(expr->value());
   5761   return ast_context()->ReturnInstruction(instr, expr->id());
   5762 }
   5763 
   5764 
   5765 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
   5766   DCHECK(!HasStackOverflow());
   5767   DCHECK(current_block() != NULL);
   5768   DCHECK(current_block()->HasPredecessor());
   5769   Callable callable = CodeFactory::FastCloneRegExp(isolate());
   5770   HValue* values[] = {
   5771       context(), AddThisFunction(), Add<HConstant>(expr->literal_index()),
   5772       Add<HConstant>(expr->pattern()), Add<HConstant>(expr->flags())};
   5773   HConstant* stub_value = Add<HConstant>(callable.code());
   5774   HInstruction* instr = New<HCallWithDescriptor>(
   5775       stub_value, 0, callable.descriptor(),
   5776       Vector<HValue*>(values, arraysize(values)), NORMAL_CALL);
   5777   return ast_context()->ReturnInstruction(instr, expr->id());
   5778 }
   5779 
   5780 
   5781 static bool CanInlinePropertyAccess(Handle<Map> map) {
   5782   if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
   5783   if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
   5784   return map->IsJSObjectMap() && !map->is_dictionary_map() &&
   5785          !map->has_named_interceptor() &&
   5786          // TODO(verwaest): Whitelist contexts to which we have access.
   5787          !map->is_access_check_needed();
   5788 }
   5789 
   5790 
   5791 // Determines whether the given array or object literal boilerplate satisfies
   5792 // all limits to be considered for fast deep-copying and computes the total
   5793 // size of all objects that are part of the graph.
   5794 static bool IsFastLiteral(Handle<JSObject> boilerplate,
   5795                           int max_depth,
   5796                           int* max_properties) {
   5797   if (boilerplate->map()->is_deprecated() &&
   5798       !JSObject::TryMigrateInstance(boilerplate)) {
   5799     return false;
   5800   }
   5801 
   5802   DCHECK(max_depth >= 0 && *max_properties >= 0);
   5803   if (max_depth == 0) return false;
   5804 
   5805   Isolate* isolate = boilerplate->GetIsolate();
   5806   Handle<FixedArrayBase> elements(boilerplate->elements());
   5807   if (elements->length() > 0 &&
   5808       elements->map() != isolate->heap()->fixed_cow_array_map()) {
   5809     if (boilerplate->HasFastSmiOrObjectElements()) {
   5810       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
   5811       int length = elements->length();
   5812       for (int i = 0; i < length; i++) {
   5813         if ((*max_properties)-- == 0) return false;
   5814         Handle<Object> value(fast_elements->get(i), isolate);
   5815         if (value->IsJSObject()) {
   5816           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   5817           if (!IsFastLiteral(value_object,
   5818                              max_depth - 1,
   5819                              max_properties)) {
   5820             return false;
   5821           }
   5822         }
   5823       }
   5824     } else if (!boilerplate->HasFastDoubleElements()) {
   5825       return false;
   5826     }
   5827   }
   5828 
   5829   Handle<FixedArray> properties(boilerplate->properties());
   5830   if (properties->length() > 0) {
   5831     return false;
   5832   } else {
   5833     Handle<DescriptorArray> descriptors(
   5834         boilerplate->map()->instance_descriptors());
   5835     int limit = boilerplate->map()->NumberOfOwnDescriptors();
   5836     for (int i = 0; i < limit; i++) {
   5837       PropertyDetails details = descriptors->GetDetails(i);
   5838       if (details.type() != DATA) continue;
   5839       if ((*max_properties)-- == 0) return false;
   5840       FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
   5841       if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
   5842       Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
   5843                            isolate);
   5844       if (value->IsJSObject()) {
   5845         Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   5846         if (!IsFastLiteral(value_object,
   5847                            max_depth - 1,
   5848                            max_properties)) {
   5849           return false;
   5850         }
   5851       }
   5852     }
   5853   }
   5854   return true;
   5855 }
   5856 
   5857 
   5858 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
   5859   DCHECK(!HasStackOverflow());
   5860   DCHECK(current_block() != NULL);
   5861   DCHECK(current_block()->HasPredecessor());
   5862 
   5863   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
   5864   HInstruction* literal;
   5865 
   5866   // Check whether to use fast or slow deep-copying for boilerplate.
   5867   int max_properties = kMaxFastLiteralProperties;
   5868   Handle<Object> literals_cell(
   5869       closure->literals()->literal(expr->literal_index()), isolate());
   5870   Handle<AllocationSite> site;
   5871   Handle<JSObject> boilerplate;
   5872   if (!literals_cell->IsUndefined()) {
   5873     // Retrieve the boilerplate
   5874     site = Handle<AllocationSite>::cast(literals_cell);
   5875     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
   5876                                    isolate());
   5877   }
   5878 
   5879   if (!boilerplate.is_null() &&
   5880       IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
   5881     AllocationSiteUsageContext site_context(isolate(), site, false);
   5882     site_context.EnterNewScope();
   5883     literal = BuildFastLiteral(boilerplate, &site_context);
   5884     site_context.ExitScope(site, boilerplate);
   5885   } else {
   5886     NoObservableSideEffectsScope no_effects(this);
   5887     Handle<FixedArray> constant_properties = expr->constant_properties();
   5888     int literal_index = expr->literal_index();
   5889     int flags = expr->ComputeFlags(true);
   5890 
   5891     Add<HPushArguments>(AddThisFunction(), Add<HConstant>(literal_index),
   5892                         Add<HConstant>(constant_properties),
   5893                         Add<HConstant>(flags));
   5894 
   5895     Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
   5896     literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
   5897   }
   5898 
   5899   // The object is expected in the bailout environment during computation
   5900   // of the property values and is the value of the entire expression.
   5901   Push(literal);
   5902   for (int i = 0; i < expr->properties()->length(); i++) {
   5903     ObjectLiteral::Property* property = expr->properties()->at(i);
   5904     if (property->is_computed_name()) return Bailout(kComputedPropertyName);
   5905     if (property->IsCompileTimeValue()) continue;
   5906 
   5907     Literal* key = property->key()->AsLiteral();
   5908     Expression* value = property->value();
   5909 
   5910     switch (property->kind()) {
   5911       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
   5912         DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
   5913         // Fall through.
   5914       case ObjectLiteral::Property::COMPUTED:
   5915         // It is safe to use [[Put]] here because the boilerplate already
   5916         // contains computed properties with an uninitialized value.
   5917         if (key->value()->IsInternalizedString()) {
   5918           if (property->emit_store()) {
   5919             CHECK_ALIVE(VisitForValue(value));
   5920             HValue* value = Pop();
   5921 
   5922             Handle<Map> map = property->GetReceiverType();
   5923             Handle<String> name = key->AsPropertyName();
   5924             HValue* store;
   5925             FeedbackVectorSlot slot = property->GetSlot();
   5926             if (map.is_null()) {
   5927               // If we don't know the monomorphic type, do a generic store.
   5928               CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot, literal,
   5929                                                     name, value));
   5930             } else {
   5931               PropertyAccessInfo info(this, STORE, map, name);
   5932               if (info.CanAccessMonomorphic()) {
   5933                 HValue* checked_literal = Add<HCheckMaps>(literal, map);
   5934                 DCHECK(!info.IsAccessorConstant());
   5935                 store = BuildMonomorphicAccess(
   5936                     &info, literal, checked_literal, value,
   5937                     BailoutId::None(), BailoutId::None());
   5938               } else {
   5939                 CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot,
   5940                                                       literal, name, value));
   5941               }
   5942             }
   5943             if (store->IsInstruction()) {
   5944               AddInstruction(HInstruction::cast(store));
   5945             }
   5946             DCHECK(store->HasObservableSideEffects());
   5947             Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
   5948 
   5949             // Add [[HomeObject]] to function literals.
   5950             if (FunctionLiteral::NeedsHomeObject(property->value())) {
   5951               Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
   5952               HInstruction* store_home = BuildNamedGeneric(
   5953                   STORE, NULL, property->GetSlot(1), value, sym, literal);
   5954               AddInstruction(store_home);
   5955               DCHECK(store_home->HasObservableSideEffects());
   5956               Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
   5957             }
   5958           } else {
   5959             CHECK_ALIVE(VisitForEffect(value));
   5960           }
   5961           break;
   5962         }
   5963         // Fall through.
   5964       case ObjectLiteral::Property::PROTOTYPE:
   5965       case ObjectLiteral::Property::SETTER:
   5966       case ObjectLiteral::Property::GETTER:
   5967         return Bailout(kObjectLiteralWithComplexProperty);
   5968       default: UNREACHABLE();
   5969     }
   5970   }
   5971 
   5972   if (expr->has_function()) {
   5973     // Return the result of the transformation to fast properties
   5974     // instead of the original since this operation changes the map
   5975     // of the object. This makes sure that the original object won't
   5976     // be used by other optimized code before it is transformed
   5977     // (e.g. because of code motion).
   5978     HToFastProperties* result = Add<HToFastProperties>(Pop());
   5979     return ast_context()->ReturnValue(result);
   5980   } else {
   5981     return ast_context()->ReturnValue(Pop());
   5982   }
   5983 }
   5984 
   5985 
   5986 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
   5987   DCHECK(!HasStackOverflow());
   5988   DCHECK(current_block() != NULL);
   5989   DCHECK(current_block()->HasPredecessor());
   5990   ZoneList<Expression*>* subexprs = expr->values();
   5991   int length = subexprs->length();
   5992   HInstruction* literal;
   5993 
   5994   Handle<AllocationSite> site;
   5995   Handle<LiteralsArray> literals(environment()->closure()->literals(),
   5996                                  isolate());
   5997   bool uninitialized = false;
   5998   Handle<Object> literals_cell(literals->literal(expr->literal_index()),
   5999                                isolate());
   6000   Handle<JSObject> boilerplate_object;
   6001   if (literals_cell->IsUndefined()) {
   6002     uninitialized = true;
   6003     Handle<Object> raw_boilerplate;
   6004     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
   6005         isolate(), raw_boilerplate,
   6006         Runtime::CreateArrayLiteralBoilerplate(
   6007             isolate(), literals, expr->constant_elements(),
   6008             is_strong(function_language_mode())),
   6009         Bailout(kArrayBoilerplateCreationFailed));
   6010 
   6011     boilerplate_object = Handle<JSObject>::cast(raw_boilerplate);
   6012     AllocationSiteCreationContext creation_context(isolate());
   6013     site = creation_context.EnterNewScope();
   6014     if (JSObject::DeepWalk(boilerplate_object, &creation_context).is_null()) {
   6015       return Bailout(kArrayBoilerplateCreationFailed);
   6016     }
   6017     creation_context.ExitScope(site, boilerplate_object);
   6018     literals->set_literal(expr->literal_index(), *site);
   6019 
   6020     if (boilerplate_object->elements()->map() ==
   6021         isolate()->heap()->fixed_cow_array_map()) {
   6022       isolate()->counters()->cow_arrays_created_runtime()->Increment();
   6023     }
   6024   } else {
   6025     DCHECK(literals_cell->IsAllocationSite());
   6026     site = Handle<AllocationSite>::cast(literals_cell);
   6027     boilerplate_object = Handle<JSObject>(
   6028         JSObject::cast(site->transition_info()), isolate());
   6029   }
   6030 
   6031   DCHECK(!boilerplate_object.is_null());
   6032   DCHECK(site->SitePointsToLiteral());
   6033 
   6034   ElementsKind boilerplate_elements_kind =
   6035       boilerplate_object->GetElementsKind();
   6036 
   6037   // Check whether to use fast or slow deep-copying for boilerplate.
   6038   int max_properties = kMaxFastLiteralProperties;
   6039   if (IsFastLiteral(boilerplate_object,
   6040                     kMaxFastLiteralDepth,
   6041                     &max_properties)) {
   6042     AllocationSiteUsageContext site_context(isolate(), site, false);
   6043     site_context.EnterNewScope();
   6044     literal = BuildFastLiteral(boilerplate_object, &site_context);
   6045     site_context.ExitScope(site, boilerplate_object);
   6046   } else {
   6047     NoObservableSideEffectsScope no_effects(this);
   6048     // Boilerplate already exists and constant elements are never accessed,
   6049     // pass an empty fixed array to the runtime function instead.
   6050     Handle<FixedArray> constants = isolate()->factory()->empty_fixed_array();
   6051     int literal_index = expr->literal_index();
   6052     int flags = expr->ComputeFlags(true);
   6053 
   6054     Add<HPushArguments>(AddThisFunction(), Add<HConstant>(literal_index),
   6055                         Add<HConstant>(constants), Add<HConstant>(flags));
   6056 
   6057     Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
   6058     literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
   6059 
   6060     // Register to deopt if the boilerplate ElementsKind changes.
   6061     top_info()->dependencies()->AssumeTransitionStable(site);
   6062   }
   6063 
   6064   // The array is expected in the bailout environment during computation
   6065   // of the property values and is the value of the entire expression.
   6066   Push(literal);
   6067 
   6068   HInstruction* elements = NULL;
   6069 
   6070   for (int i = 0; i < length; i++) {
   6071     Expression* subexpr = subexprs->at(i);
   6072     if (subexpr->IsSpread()) {
   6073       return Bailout(kSpread);
   6074     }
   6075 
   6076     // If the subexpression is a literal or a simple materialized literal it
   6077     // is already set in the cloned array.
   6078     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
   6079 
   6080     CHECK_ALIVE(VisitForValue(subexpr));
   6081     HValue* value = Pop();
   6082     if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
   6083 
   6084     elements = AddLoadElements(literal);
   6085 
   6086     HValue* key = Add<HConstant>(i);
   6087 
   6088     switch (boilerplate_elements_kind) {
   6089       case FAST_SMI_ELEMENTS:
   6090       case FAST_HOLEY_SMI_ELEMENTS:
   6091       case FAST_ELEMENTS:
   6092       case FAST_HOLEY_ELEMENTS:
   6093       case FAST_DOUBLE_ELEMENTS:
   6094       case FAST_HOLEY_DOUBLE_ELEMENTS: {
   6095         HStoreKeyed* instr = Add<HStoreKeyed>(elements, key, value, nullptr,
   6096                                               boilerplate_elements_kind);
   6097         instr->SetUninitialized(uninitialized);
   6098         break;
   6099       }
   6100       default:
   6101         UNREACHABLE();
   6102         break;
   6103     }
   6104 
   6105     Add<HSimulate>(expr->GetIdForElement(i));
   6106   }
   6107 
   6108   return ast_context()->ReturnValue(Pop());
   6109 }
   6110 
   6111 
   6112 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
   6113                                                 Handle<Map> map) {
   6114   BuildCheckHeapObject(object);
   6115   return Add<HCheckMaps>(object, map);
   6116 }
   6117 
   6118 
   6119 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
   6120     PropertyAccessInfo* info,
   6121     HValue* checked_object) {
   6122   // See if this is a load for an immutable property
   6123   if (checked_object->ActualValue()->IsConstant()) {
   6124     Handle<Object> object(
   6125         HConstant::cast(checked_object->ActualValue())->handle(isolate()));
   6126 
   6127     if (object->IsJSObject()) {
   6128       LookupIterator it(object, info->name(),
   6129                         LookupIterator::OWN_SKIP_INTERCEPTOR);
   6130       Handle<Object> value = JSReceiver::GetDataProperty(&it);
   6131       if (it.IsFound() && it.IsReadOnly() && !it.IsConfigurable()) {
   6132         return New<HConstant>(value);
   6133       }
   6134     }
   6135   }
   6136 
   6137   HObjectAccess access = info->access();
   6138   if (access.representation().IsDouble() &&
   6139       (!FLAG_unbox_double_fields || !access.IsInobject())) {
   6140     // Load the heap number.
   6141     checked_object = Add<HLoadNamedField>(
   6142         checked_object, nullptr,
   6143         access.WithRepresentation(Representation::Tagged()));
   6144     // Load the double value from it.
   6145     access = HObjectAccess::ForHeapNumberValue();
   6146   }
   6147 
   6148   SmallMapList* map_list = info->field_maps();
   6149   if (map_list->length() == 0) {
   6150     return New<HLoadNamedField>(checked_object, checked_object, access);
   6151   }
   6152 
   6153   UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
   6154   for (int i = 0; i < map_list->length(); ++i) {
   6155     maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
   6156   }
   6157   return New<HLoadNamedField>(
   6158       checked_object, checked_object, access, maps, info->field_type());
   6159 }
   6160 
   6161 
   6162 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
   6163     PropertyAccessInfo* info,
   6164     HValue* checked_object,
   6165     HValue* value) {
   6166   bool transition_to_field = info->IsTransition();
   6167   // TODO(verwaest): Move this logic into PropertyAccessInfo.
   6168   HObjectAccess field_access = info->access();
   6169 
   6170   HStoreNamedField *instr;
   6171   if (field_access.representation().IsDouble() &&
   6172       (!FLAG_unbox_double_fields || !field_access.IsInobject())) {
   6173     HObjectAccess heap_number_access =
   6174         field_access.WithRepresentation(Representation::Tagged());
   6175     if (transition_to_field) {
   6176       // The store requires a mutable HeapNumber to be allocated.
   6177       NoObservableSideEffectsScope no_side_effects(this);
   6178       HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
   6179 
   6180       // TODO(hpayer): Allocation site pretenuring support.
   6181       HInstruction* heap_number = Add<HAllocate>(heap_number_size,
   6182           HType::HeapObject(),
   6183           NOT_TENURED,
   6184           MUTABLE_HEAP_NUMBER_TYPE);
   6185       AddStoreMapConstant(
   6186           heap_number, isolate()->factory()->mutable_heap_number_map());
   6187       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
   6188                             value);
   6189       instr = New<HStoreNamedField>(checked_object->ActualValue(),
   6190                                     heap_number_access,
   6191                                     heap_number);
   6192     } else {
   6193       // Already holds a HeapNumber; load the box and write its value field.
   6194       HInstruction* heap_number =
   6195           Add<HLoadNamedField>(checked_object, nullptr, heap_number_access);
   6196       instr = New<HStoreNamedField>(heap_number,
   6197                                     HObjectAccess::ForHeapNumberValue(),
   6198                                     value, STORE_TO_INITIALIZED_ENTRY);
   6199     }
   6200   } else {
   6201     if (field_access.representation().IsHeapObject()) {
   6202       BuildCheckHeapObject(value);
   6203     }
   6204 
   6205     if (!info->field_maps()->is_empty()) {
   6206       DCHECK(field_access.representation().IsHeapObject());
   6207       value = Add<HCheckMaps>(value, info->field_maps());
   6208     }
   6209 
   6210     // This is a normal store.
   6211     instr = New<HStoreNamedField>(
   6212         checked_object->ActualValue(), field_access, value,
   6213         transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
   6214   }
   6215 
   6216   if (transition_to_field) {
   6217     Handle<Map> transition(info->transition());
   6218     DCHECK(!transition->is_deprecated());
   6219     instr->SetTransition(Add<HConstant>(transition));
   6220   }
   6221   return instr;
   6222 }
   6223 
   6224 
   6225 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
   6226     PropertyAccessInfo* info) {
   6227   if (!CanInlinePropertyAccess(map_)) return false;
   6228 
   6229   // Currently only handle Type::Number as a polymorphic case.
   6230   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
   6231   // instruction.
   6232   if (IsNumberType()) return false;
   6233 
   6234   // Values are only compatible for monomorphic load if they all behave the same
   6235   // regarding value wrappers.
   6236   if (IsValueWrapped() != info->IsValueWrapped()) return false;
   6237 
   6238   if (!LookupDescriptor()) return false;
   6239 
   6240   if (!IsFound()) {
   6241     return (!info->IsFound() || info->has_holder()) &&
   6242            map()->prototype() == info->map()->prototype();
   6243   }
   6244 
   6245   // Mismatch if the other access info found the property in the prototype
   6246   // chain.
   6247   if (info->has_holder()) return false;
   6248 
   6249   if (IsAccessorConstant()) {
   6250     return accessor_.is_identical_to(info->accessor_) &&
   6251         api_holder_.is_identical_to(info->api_holder_);
   6252   }
   6253 
   6254   if (IsDataConstant()) {
   6255     return constant_.is_identical_to(info->constant_);
   6256   }
   6257 
   6258   DCHECK(IsData());
   6259   if (!info->IsData()) return false;
   6260 
   6261   Representation r = access_.representation();
   6262   if (IsLoad()) {
   6263     if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
   6264   } else {
   6265     if (!info->access_.representation().IsCompatibleForStore(r)) return false;
   6266   }
   6267   if (info->access_.offset() != access_.offset()) return false;
   6268   if (info->access_.IsInobject() != access_.IsInobject()) return false;
   6269   if (IsLoad()) {
   6270     if (field_maps_.is_empty()) {
   6271       info->field_maps_.Clear();
   6272     } else if (!info->field_maps_.is_empty()) {
   6273       for (int i = 0; i < field_maps_.length(); ++i) {
   6274         info->field_maps_.AddMapIfMissing(field_maps_.at(i), info->zone());
   6275       }
   6276       info->field_maps_.Sort();
   6277     }
   6278   } else {
   6279     // We can only merge stores that agree on their field maps. The comparison
   6280     // below is safe, since we keep the field maps sorted.
   6281     if (field_maps_.length() != info->field_maps_.length()) return false;
   6282     for (int i = 0; i < field_maps_.length(); ++i) {
   6283       if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) {
   6284         return false;
   6285       }
   6286     }
   6287   }
   6288   info->GeneralizeRepresentation(r);
   6289   info->field_type_ = info->field_type_.Combine(field_type_);
   6290   return true;
   6291 }
   6292 
   6293 
   6294 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
   6295   if (!map_->IsJSObjectMap()) return true;
   6296   LookupDescriptor(*map_, *name_);
   6297   return LoadResult(map_);
   6298 }
   6299 
   6300 
   6301 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
   6302   if (!IsLoad() && IsProperty() && IsReadOnly()) {
   6303     return false;
   6304   }
   6305 
   6306   if (IsData()) {
   6307     // Construct the object field access.
   6308     int index = GetLocalFieldIndexFromMap(map);
   6309     access_ = HObjectAccess::ForField(map, index, representation(), name_);
   6310 
   6311     // Load field map for heap objects.
   6312     return LoadFieldMaps(map);
   6313   } else if (IsAccessorConstant()) {
   6314     Handle<Object> accessors = GetAccessorsFromMap(map);
   6315     if (!accessors->IsAccessorPair()) return false;
   6316     Object* raw_accessor =
   6317         IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
   6318                  : Handle<AccessorPair>::cast(accessors)->setter();
   6319     if (!raw_accessor->IsJSFunction()) return false;
   6320     Handle<JSFunction> accessor = handle(JSFunction::cast(raw_accessor));
   6321     if (accessor->shared()->IsApiFunction()) {
   6322       CallOptimization call_optimization(accessor);
   6323       if (call_optimization.is_simple_api_call()) {
   6324         CallOptimization::HolderLookup holder_lookup;
   6325         api_holder_ =
   6326             call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
   6327       }
   6328     }
   6329     accessor_ = accessor;
   6330   } else if (IsDataConstant()) {
   6331     constant_ = GetConstantFromMap(map);
   6332   }
   6333 
   6334   return true;
   6335 }
   6336 
   6337 
   6338 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
   6339     Handle<Map> map) {
   6340   // Clear any previously collected field maps/type.
   6341   field_maps_.Clear();
   6342   field_type_ = HType::Tagged();
   6343 
   6344   // Figure out the field type from the accessor map.
   6345   Handle<HeapType> field_type = GetFieldTypeFromMap(map);
   6346 
   6347   // Collect the (stable) maps from the field type.
   6348   int num_field_maps = field_type->NumClasses();
   6349   if (num_field_maps > 0) {
   6350     DCHECK(access_.representation().IsHeapObject());
   6351     field_maps_.Reserve(num_field_maps, zone());
   6352     HeapType::Iterator<Map> it = field_type->Classes();
   6353     while (!it.Done()) {
   6354       Handle<Map> field_map = it.Current();
   6355       if (!field_map->is_stable()) {
   6356         field_maps_.Clear();
   6357         break;
   6358       }
   6359       field_maps_.Add(field_map, zone());
   6360       it.Advance();
   6361     }
   6362   }
   6363 
   6364   if (field_maps_.is_empty()) {
   6365     // Store is not safe if the field map was cleared.
   6366     return IsLoad() || !field_type->Is(HeapType::None());
   6367   }
   6368 
   6369   field_maps_.Sort();
   6370   DCHECK_EQ(num_field_maps, field_maps_.length());
   6371 
   6372   // Determine field HType from field HeapType.
   6373   field_type_ = HType::FromType<HeapType>(field_type);
   6374   DCHECK(field_type_.IsHeapObject());
   6375 
   6376   // Add dependency on the map that introduced the field.
   6377   top_info()->dependencies()->AssumeFieldType(GetFieldOwnerFromMap(map));
   6378   return true;
   6379 }
   6380 
   6381 
   6382 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
   6383   Handle<Map> map = this->map();
   6384 
   6385   while (map->prototype()->IsJSObject()) {
   6386     holder_ = handle(JSObject::cast(map->prototype()));
   6387     if (holder_->map()->is_deprecated()) {
   6388       JSObject::TryMigrateInstance(holder_);
   6389     }
   6390     map = Handle<Map>(holder_->map());
   6391     if (!CanInlinePropertyAccess(map)) {
   6392       NotFound();
   6393       return false;
   6394     }
   6395     LookupDescriptor(*map, *name_);
   6396     if (IsFound()) return LoadResult(map);
   6397   }
   6398 
   6399   NotFound();
   6400   return !map->prototype()->IsJSReceiver();
   6401 }
   6402 
   6403 
   6404 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() {
   6405   InstanceType instance_type = map_->instance_type();
   6406   return instance_type == JS_TYPED_ARRAY_TYPE && name_->IsString() &&
   6407          IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name_));
   6408 }
   6409 
   6410 
   6411 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
   6412   if (!CanInlinePropertyAccess(map_)) return false;
   6413   if (IsJSObjectFieldAccessor()) return IsLoad();
   6414   if (IsJSArrayBufferViewFieldAccessor()) return IsLoad();
   6415   if (map_->IsJSFunctionMap() && map_->is_constructor() &&
   6416       !map_->has_non_instance_prototype() &&
   6417       name_.is_identical_to(isolate()->factory()->prototype_string())) {
   6418     return IsLoad();
   6419   }
   6420   if (!LookupDescriptor()) return false;
   6421   if (IsFound()) return IsLoad() || !IsReadOnly();
   6422   if (IsIntegerIndexedExotic()) return false;
   6423   if (!LookupInPrototypes()) return false;
   6424   if (IsLoad()) return true;
   6425 
   6426   if (IsAccessorConstant()) return true;
   6427   LookupTransition(*map_, *name_, NONE);
   6428   if (IsTransitionToData() && map_->unused_property_fields() > 0) {
   6429     // Construct the object field access.
   6430     int descriptor = transition()->LastAdded();
   6431     int index =
   6432         transition()->instance_descriptors()->GetFieldIndex(descriptor) -
   6433         map_->GetInObjectProperties();
   6434     PropertyDetails details =
   6435         transition()->instance_descriptors()->GetDetails(descriptor);
   6436     Representation representation = details.representation();
   6437     access_ = HObjectAccess::ForField(map_, index, representation, name_);
   6438 
   6439     // Load field map for heap objects.
   6440     return LoadFieldMaps(transition());
   6441   }
   6442   return false;
   6443 }
   6444 
   6445 
   6446 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
   6447     SmallMapList* maps) {
   6448   DCHECK(map_.is_identical_to(maps->first()));
   6449   if (!CanAccessMonomorphic()) return false;
   6450   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
   6451   if (maps->length() > kMaxLoadPolymorphism) return false;
   6452   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
   6453   if (GetJSObjectFieldAccess(&access)) {
   6454     for (int i = 1; i < maps->length(); ++i) {
   6455       PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
   6456       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
   6457       if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
   6458       if (!access.Equals(test_access)) return false;
   6459     }
   6460     return true;
   6461   }
   6462   if (GetJSArrayBufferViewFieldAccess(&access)) {
   6463     for (int i = 1; i < maps->length(); ++i) {
   6464       PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
   6465       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
   6466       if (!test_info.GetJSArrayBufferViewFieldAccess(&test_access)) {
   6467         return false;
   6468       }
   6469       if (!access.Equals(test_access)) return false;
   6470     }
   6471     return true;
   6472   }
   6473 
   6474   // Currently only handle numbers as a polymorphic case.
   6475   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
   6476   // instruction.
   6477   if (IsNumberType()) return false;
   6478 
   6479   // Multiple maps cannot transition to the same target map.
   6480   DCHECK(!IsLoad() || !IsTransition());
   6481   if (IsTransition() && maps->length() > 1) return false;
   6482 
   6483   for (int i = 1; i < maps->length(); ++i) {
   6484     PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
   6485     if (!test_info.IsCompatible(this)) return false;
   6486   }
   6487 
   6488   return true;
   6489 }
   6490 
   6491 
   6492 Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
   6493   Handle<JSFunction> ctor;
   6494   if (Map::GetConstructorFunction(
   6495           map_, handle(current_info()->closure()->context()->native_context()))
   6496           .ToHandle(&ctor)) {
   6497     return handle(ctor->initial_map());
   6498   }
   6499   return map_;
   6500 }
   6501 
   6502 
   6503 static bool NeedsWrapping(Handle<Map> map, Handle<JSFunction> target) {
   6504   return !map->IsJSObjectMap() &&
   6505          is_sloppy(target->shared()->language_mode()) &&
   6506          !target->shared()->native();
   6507 }
   6508 
   6509 
   6510 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor(
   6511     Handle<JSFunction> target) const {
   6512   return NeedsWrapping(map_, target);
   6513 }
   6514 
   6515 
   6516 HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
   6517     PropertyAccessInfo* info, HValue* object, HValue* checked_object,
   6518     HValue* value, BailoutId ast_id, BailoutId return_id,
   6519     bool can_inline_accessor) {
   6520   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
   6521   if (info->GetJSObjectFieldAccess(&access)) {
   6522     DCHECK(info->IsLoad());
   6523     return New<HLoadNamedField>(object, checked_object, access);
   6524   }
   6525 
   6526   if (info->GetJSArrayBufferViewFieldAccess(&access)) {
   6527     DCHECK(info->IsLoad());
   6528     checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
   6529     return New<HLoadNamedField>(object, checked_object, access);
   6530   }
   6531 
   6532   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
   6533       info->map()->IsJSFunctionMap() && info->map()->is_constructor()) {
   6534     DCHECK(!info->map()->has_non_instance_prototype());
   6535     return New<HLoadFunctionPrototype>(checked_object);
   6536   }
   6537 
   6538   HValue* checked_holder = checked_object;
   6539   if (info->has_holder()) {
   6540     Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
   6541     checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
   6542   }
   6543 
   6544   if (!info->IsFound()) {
   6545     DCHECK(info->IsLoad());
   6546     if (is_strong(function_language_mode())) {
   6547       return New<HCallRuntime>(
   6548           Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
   6549           0);
   6550     } else {
   6551       return graph()->GetConstantUndefined();
   6552     }
   6553   }
   6554 
   6555   if (info->IsData()) {
   6556     if (info->IsLoad()) {
   6557       return BuildLoadNamedField(info, checked_holder);
   6558     } else {
   6559       return BuildStoreNamedField(info, checked_object, value);
   6560     }
   6561   }
   6562 
   6563   if (info->IsTransition()) {
   6564     DCHECK(!info->IsLoad());
   6565     return BuildStoreNamedField(info, checked_object, value);
   6566   }
   6567 
   6568   if (info->IsAccessorConstant()) {
   6569     Push(checked_object);
   6570     int argument_count = 1;
   6571     if (!info->IsLoad()) {
   6572       argument_count = 2;
   6573       Push(value);
   6574     }
   6575 
   6576     if (info->NeedsWrappingFor(info->accessor())) {
   6577       HValue* function = Add<HConstant>(info->accessor());
   6578       PushArgumentsFromEnvironment(argument_count);
   6579       return New<HCallFunction>(function, argument_count,
   6580                                 ConvertReceiverMode::kNotNullOrUndefined);
   6581     } else if (FLAG_inline_accessors && can_inline_accessor) {
   6582       bool success = info->IsLoad()
   6583           ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
   6584           : TryInlineSetter(
   6585               info->accessor(), info->map(), ast_id, return_id, value);
   6586       if (success || HasStackOverflow()) return NULL;
   6587     }
   6588 
   6589     PushArgumentsFromEnvironment(argument_count);
   6590     return BuildCallConstantFunction(info->accessor(), argument_count);
   6591   }
   6592 
   6593   DCHECK(info->IsDataConstant());
   6594   if (info->IsLoad()) {
   6595     return New<HConstant>(info->constant());
   6596   } else {
   6597     return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
   6598   }
   6599 }
   6600 
   6601 
   6602 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
   6603     PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
   6604     BailoutId ast_id, BailoutId return_id, HValue* object, HValue* value,
   6605     SmallMapList* maps, Handle<Name> name) {
   6606   // Something did not match; must use a polymorphic load.
   6607   int count = 0;
   6608   HBasicBlock* join = NULL;
   6609   HBasicBlock* number_block = NULL;
   6610   bool handled_string = false;
   6611 
   6612   bool handle_smi = false;
   6613   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
   6614   int i;
   6615   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
   6616     PropertyAccessInfo info(this, access_type, maps->at(i), name);
   6617     if (info.IsStringType()) {
   6618       if (handled_string) continue;
   6619       handled_string = true;
   6620     }
   6621     if (info.CanAccessMonomorphic()) {
   6622       count++;
   6623       if (info.IsNumberType()) {
   6624         handle_smi = true;
   6625         break;
   6626       }
   6627     }
   6628   }
   6629 
   6630   if (i < maps->length()) {
   6631     count = -1;
   6632     maps->Clear();
   6633   } else {
   6634     count = 0;
   6635   }
   6636   HControlInstruction* smi_check = NULL;
   6637   handled_string = false;
   6638 
   6639   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
   6640     PropertyAccessInfo info(this, access_type, maps->at(i), name);
   6641     if (info.IsStringType()) {
   6642       if (handled_string) continue;
   6643       handled_string = true;
   6644     }
   6645     if (!info.CanAccessMonomorphic()) continue;
   6646 
   6647     if (count == 0) {
   6648       join = graph()->CreateBasicBlock();
   6649       if (handle_smi) {
   6650         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
   6651         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
   6652         number_block = graph()->CreateBasicBlock();
   6653         smi_check = New<HIsSmiAndBranch>(
   6654             object, empty_smi_block, not_smi_block);
   6655         FinishCurrentBlock(smi_check);
   6656         GotoNoSimulate(empty_smi_block, number_block);
   6657         set_current_block(not_smi_block);
   6658       } else {
   6659         BuildCheckHeapObject(object);
   6660       }
   6661     }
   6662     ++count;
   6663     HBasicBlock* if_true = graph()->CreateBasicBlock();
   6664     HBasicBlock* if_false = graph()->CreateBasicBlock();
   6665     HUnaryControlInstruction* compare;
   6666 
   6667     HValue* dependency;
   6668     if (info.IsNumberType()) {
   6669       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
   6670       compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
   6671       dependency = smi_check;
   6672     } else if (info.IsStringType()) {
   6673       compare = New<HIsStringAndBranch>(object, if_true, if_false);
   6674       dependency = compare;
   6675     } else {
   6676       compare = New<HCompareMap>(object, info.map(), if_true, if_false);
   6677       dependency = compare;
   6678     }
   6679     FinishCurrentBlock(compare);
   6680 
   6681     if (info.IsNumberType()) {
   6682       GotoNoSimulate(if_true, number_block);
   6683       if_true = number_block;
   6684     }
   6685 
   6686     set_current_block(if_true);
   6687 
   6688     HValue* access =
   6689         BuildMonomorphicAccess(&info, object, dependency, value, ast_id,
   6690                                return_id, FLAG_polymorphic_inlining);
   6691 
   6692     HValue* result = NULL;
   6693     switch (access_type) {
   6694       case LOAD:
   6695         result = access;
   6696         break;
   6697       case STORE:
   6698         result = value;
   6699         break;
   6700     }
   6701 
   6702     if (access == NULL) {
   6703       if (HasStackOverflow()) return;
   6704     } else {
   6705       if (access->IsInstruction()) {
   6706         HInstruction* instr = HInstruction::cast(access);
   6707         if (!instr->IsLinked()) AddInstruction(instr);
   6708       }
   6709       if (!ast_context()->IsEffect()) Push(result);
   6710     }
   6711 
   6712     if (current_block() != NULL) Goto(join);
   6713     set_current_block(if_false);
   6714   }
   6715 
   6716   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
   6717   // know about and do not want to handle ones we've never seen.  Otherwise
   6718   // use a generic IC.
   6719   if (count == maps->length() && FLAG_deoptimize_uncommon_cases) {
   6720     FinishExitWithHardDeoptimization(
   6721         Deoptimizer::kUnknownMapInPolymorphicAccess);
   6722   } else {
   6723     HInstruction* instr =
   6724         BuildNamedGeneric(access_type, expr, slot, object, name, value);
   6725     AddInstruction(instr);
   6726     if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
   6727 
   6728     if (join != NULL) {
   6729       Goto(join);
   6730     } else {
   6731       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6732       if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
   6733       return;
   6734     }
   6735   }
   6736 
   6737   DCHECK(join != NULL);
   6738   if (join->HasPredecessor()) {
   6739     join->SetJoinId(ast_id);
   6740     set_current_block(join);
   6741     if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
   6742   } else {
   6743     set_current_block(NULL);
   6744   }
   6745 }
   6746 
   6747 
   6748 static bool ComputeReceiverTypes(Expression* expr,
   6749                                  HValue* receiver,
   6750                                  SmallMapList** t,
   6751                                  Zone* zone) {
   6752   SmallMapList* maps = expr->GetReceiverTypes();
   6753   *t = maps;
   6754   bool monomorphic = expr->IsMonomorphic();
   6755   if (maps != NULL && receiver->HasMonomorphicJSObjectType()) {
   6756     Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
   6757     maps->FilterForPossibleTransitions(root_map);
   6758     monomorphic = maps->length() == 1;
   6759   }
   6760   return monomorphic && CanInlinePropertyAccess(maps->first());
   6761 }
   6762 
   6763 
   6764 static bool AreStringTypes(SmallMapList* maps) {
   6765   for (int i = 0; i < maps->length(); i++) {
   6766     if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
   6767   }
   6768   return true;
   6769 }
   6770 
   6771 
   6772 void HOptimizedGraphBuilder::BuildStore(Expression* expr, Property* prop,
   6773                                         FeedbackVectorSlot slot,
   6774                                         BailoutId ast_id, BailoutId return_id,
   6775                                         bool is_uninitialized) {
   6776   if (!prop->key()->IsPropertyName()) {
   6777     // Keyed store.
   6778     HValue* value = Pop();
   6779     HValue* key = Pop();
   6780     HValue* object = Pop();
   6781     bool has_side_effects = false;
   6782     HValue* result =
   6783         HandleKeyedElementAccess(object, key, value, expr, slot, ast_id,
   6784                                  return_id, STORE, &has_side_effects);
   6785     if (has_side_effects) {
   6786       if (!ast_context()->IsEffect()) Push(value);
   6787       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6788       if (!ast_context()->IsEffect()) Drop(1);
   6789     }
   6790     if (result == NULL) return;
   6791     return ast_context()->ReturnValue(value);
   6792   }
   6793 
   6794   // Named store.
   6795   HValue* value = Pop();
   6796   HValue* object = Pop();
   6797 
   6798   Literal* key = prop->key()->AsLiteral();
   6799   Handle<String> name = Handle<String>::cast(key->value());
   6800   DCHECK(!name.is_null());
   6801 
   6802   HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, slot,
   6803                                     object, name, value, is_uninitialized);
   6804   if (access == NULL) return;
   6805 
   6806   if (!ast_context()->IsEffect()) Push(value);
   6807   if (access->IsInstruction()) AddInstruction(HInstruction::cast(access));
   6808   if (access->HasObservableSideEffects()) {
   6809     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6810   }
   6811   if (!ast_context()->IsEffect()) Drop(1);
   6812   return ast_context()->ReturnValue(value);
   6813 }
   6814 
   6815 
   6816 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
   6817   Property* prop = expr->target()->AsProperty();
   6818   DCHECK(prop != NULL);
   6819   CHECK_ALIVE(VisitForValue(prop->obj()));
   6820   if (!prop->key()->IsPropertyName()) {
   6821     CHECK_ALIVE(VisitForValue(prop->key()));
   6822   }
   6823   CHECK_ALIVE(VisitForValue(expr->value()));
   6824   BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
   6825              expr->AssignmentId(), expr->IsUninitialized());
   6826 }
   6827 
   6828 
   6829 // Because not every expression has a position and there is not common
   6830 // superclass of Assignment and CountOperation, we cannot just pass the
   6831 // owning expression instead of position and ast_id separately.
   6832 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
   6833     Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) {
   6834   Handle<JSGlobalObject> global(current_info()->global_object());
   6835 
   6836   // Lookup in script contexts.
   6837   {
   6838     Handle<ScriptContextTable> script_contexts(
   6839         global->native_context()->script_context_table());
   6840     ScriptContextTable::LookupResult lookup;
   6841     if (ScriptContextTable::Lookup(script_contexts, var->name(), &lookup)) {
   6842       if (lookup.mode == CONST) {
   6843         return Bailout(kNonInitializerAssignmentToConst);
   6844       }
   6845       Handle<Context> script_context =
   6846           ScriptContextTable::GetContext(script_contexts, lookup.context_index);
   6847 
   6848       Handle<Object> current_value =
   6849           FixedArray::get(script_context, lookup.slot_index);
   6850 
   6851       // If the values is not the hole, it will stay initialized,
   6852       // so no need to generate a check.
   6853       if (*current_value == *isolate()->factory()->the_hole_value()) {
   6854         return Bailout(kReferenceToUninitializedVariable);
   6855       }
   6856 
   6857       HStoreNamedField* instr = Add<HStoreNamedField>(
   6858           Add<HConstant>(script_context),
   6859           HObjectAccess::ForContextSlot(lookup.slot_index), value);
   6860       USE(instr);
   6861       DCHECK(instr->HasObservableSideEffects());
   6862       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6863       return;
   6864     }
   6865   }
   6866 
   6867   LookupIterator it(global, var->name(), LookupIterator::OWN);
   6868   GlobalPropertyAccess type = LookupGlobalProperty(var, &it, STORE);
   6869   if (type == kUseCell) {
   6870     Handle<PropertyCell> cell = it.GetPropertyCell();
   6871     top_info()->dependencies()->AssumePropertyCell(cell);
   6872     auto cell_type = it.property_details().cell_type();
   6873     if (cell_type == PropertyCellType::kConstant ||
   6874         cell_type == PropertyCellType::kUndefined) {
   6875       Handle<Object> constant(cell->value(), isolate());
   6876       if (value->IsConstant()) {
   6877         HConstant* c_value = HConstant::cast(value);
   6878         if (!constant.is_identical_to(c_value->handle(isolate()))) {
   6879           Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
   6880                            Deoptimizer::EAGER);
   6881         }
   6882       } else {
   6883         HValue* c_constant = Add<HConstant>(constant);
   6884         IfBuilder builder(this);
   6885         if (constant->IsNumber()) {
   6886           builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
   6887         } else {
   6888           builder.If<HCompareObjectEqAndBranch>(value, c_constant);
   6889         }
   6890         builder.Then();
   6891         builder.Else();
   6892         Add<HDeoptimize>(Deoptimizer::kConstantGlobalVariableAssignment,
   6893                          Deoptimizer::EAGER);
   6894         builder.End();
   6895       }
   6896     }
   6897     HConstant* cell_constant = Add<HConstant>(cell);
   6898     auto access = HObjectAccess::ForPropertyCellValue();
   6899     if (cell_type == PropertyCellType::kConstantType) {
   6900       switch (cell->GetConstantType()) {
   6901         case PropertyCellConstantType::kSmi:
   6902           access = access.WithRepresentation(Representation::Smi());
   6903           break;
   6904         case PropertyCellConstantType::kStableMap: {
   6905           // The map may no longer be stable, deopt if it's ever different from
   6906           // what is currently there, which will allow for restablization.
   6907           Handle<Map> map(HeapObject::cast(cell->value())->map());
   6908           Add<HCheckHeapObject>(value);
   6909           value = Add<HCheckMaps>(value, map);
   6910           access = access.WithRepresentation(Representation::HeapObject());
   6911           break;
   6912         }
   6913       }
   6914     }
   6915     HInstruction* instr = Add<HStoreNamedField>(cell_constant, access, value);
   6916     instr->ClearChangesFlag(kInobjectFields);
   6917     instr->SetChangesFlag(kGlobalVars);
   6918     if (instr->HasObservableSideEffects()) {
   6919       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6920     }
   6921   } else {
   6922     HValue* global_object = Add<HLoadNamedField>(
   6923         BuildGetNativeContext(), nullptr,
   6924         HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX));
   6925     HStoreNamedGeneric* instr =
   6926         Add<HStoreNamedGeneric>(global_object, var->name(), value,
   6927                                 function_language_mode(), PREMONOMORPHIC);
   6928     Handle<TypeFeedbackVector> vector =
   6929         handle(current_feedback_vector(), isolate());
   6930     instr->SetVectorAndSlot(vector, slot);
   6931     USE(instr);
   6932     DCHECK(instr->HasObservableSideEffects());
   6933     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6934   }
   6935 }
   6936 
   6937 
   6938 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
   6939   Expression* target = expr->target();
   6940   VariableProxy* proxy = target->AsVariableProxy();
   6941   Property* prop = target->AsProperty();
   6942   DCHECK(proxy == NULL || prop == NULL);
   6943 
   6944   // We have a second position recorded in the FullCodeGenerator to have
   6945   // type feedback for the binary operation.
   6946   BinaryOperation* operation = expr->binary_operation();
   6947 
   6948   if (proxy != NULL) {
   6949     Variable* var = proxy->var();
   6950     if (var->mode() == LET)  {
   6951       return Bailout(kUnsupportedLetCompoundAssignment);
   6952     }
   6953 
   6954     CHECK_ALIVE(VisitForValue(operation));
   6955 
   6956     switch (var->location()) {
   6957       case VariableLocation::GLOBAL:
   6958       case VariableLocation::UNALLOCATED:
   6959         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
   6960                                        expr->AssignmentId());
   6961         break;
   6962 
   6963       case VariableLocation::PARAMETER:
   6964       case VariableLocation::LOCAL:
   6965         if (var->mode() == CONST_LEGACY)  {
   6966           return Bailout(kUnsupportedConstCompoundAssignment);
   6967         }
   6968         if (var->mode() == CONST) {
   6969           return Bailout(kNonInitializerAssignmentToConst);
   6970         }
   6971         BindIfLive(var, Top());
   6972         break;
   6973 
   6974       case VariableLocation::CONTEXT: {
   6975         // Bail out if we try to mutate a parameter value in a function
   6976         // using the arguments object.  We do not (yet) correctly handle the
   6977         // arguments property of the function.
   6978         if (current_info()->scope()->arguments() != NULL) {
   6979           // Parameters will be allocated to context slots.  We have no
   6980           // direct way to detect that the variable is a parameter so we do
   6981           // a linear search of the parameter variables.
   6982           int count = current_info()->scope()->num_parameters();
   6983           for (int i = 0; i < count; ++i) {
   6984             if (var == current_info()->scope()->parameter(i)) {
   6985               Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
   6986             }
   6987           }
   6988         }
   6989 
   6990         HStoreContextSlot::Mode mode;
   6991 
   6992         switch (var->mode()) {
   6993           case LET:
   6994             mode = HStoreContextSlot::kCheckDeoptimize;
   6995             break;
   6996           case CONST:
   6997             return Bailout(kNonInitializerAssignmentToConst);
   6998           case CONST_LEGACY:
   6999             return ast_context()->ReturnValue(Pop());
   7000           default:
   7001             mode = HStoreContextSlot::kNoCheck;
   7002         }
   7003 
   7004         HValue* context = BuildContextChainWalk(var);
   7005         HStoreContextSlot* instr = Add<HStoreContextSlot>(
   7006             context, var->index(), mode, Top());
   7007         if (instr->HasObservableSideEffects()) {
   7008           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   7009         }
   7010         break;
   7011       }
   7012 
   7013       case VariableLocation::LOOKUP:
   7014         return Bailout(kCompoundAssignmentToLookupSlot);
   7015     }
   7016     return ast_context()->ReturnValue(Pop());
   7017 
   7018   } else if (prop != NULL) {
   7019     CHECK_ALIVE(VisitForValue(prop->obj()));
   7020     HValue* object = Top();
   7021     HValue* key = NULL;
   7022     if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
   7023       CHECK_ALIVE(VisitForValue(prop->key()));
   7024       key = Top();
   7025     }
   7026 
   7027     CHECK_ALIVE(PushLoad(prop, object, key));
   7028 
   7029     CHECK_ALIVE(VisitForValue(expr->value()));
   7030     HValue* right = Pop();
   7031     HValue* left = Pop();
   7032 
   7033     Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
   7034 
   7035     BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
   7036                expr->AssignmentId(), expr->IsUninitialized());
   7037   } else {
   7038     return Bailout(kInvalidLhsInCompoundAssignment);
   7039   }
   7040 }
   7041 
   7042 
   7043 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
   7044   DCHECK(!HasStackOverflow());
   7045   DCHECK(current_block() != NULL);
   7046   DCHECK(current_block()->HasPredecessor());
   7047 
   7048   VariableProxy* proxy = expr->target()->AsVariableProxy();
   7049   Property* prop = expr->target()->AsProperty();
   7050   DCHECK(proxy == NULL || prop == NULL);
   7051 
   7052   if (expr->is_compound()) {
   7053     HandleCompoundAssignment(expr);
   7054     return;
   7055   }
   7056 
   7057   if (prop != NULL) {
   7058     HandlePropertyAssignment(expr);
   7059   } else if (proxy != NULL) {
   7060     Variable* var = proxy->var();
   7061 
   7062     if (var->mode() == CONST) {
   7063       if (expr->op() != Token::INIT) {
   7064         return Bailout(kNonInitializerAssignmentToConst);
   7065       }
   7066     } else if (var->mode() == CONST_LEGACY) {
   7067       if (expr->op() != Token::INIT) {
   7068         CHECK_ALIVE(VisitForValue(expr->value()));
   7069         return ast_context()->ReturnValue(Pop());
   7070       }
   7071 
   7072       if (var->IsStackAllocated()) {
   7073         // We insert a use of the old value to detect unsupported uses of const
   7074         // variables (e.g. initialization inside a loop).
   7075         HValue* old_value = environment()->Lookup(var);
   7076         Add<HUseConst>(old_value);
   7077       }
   7078     }
   7079 
   7080     if (proxy->IsArguments()) return Bailout(kAssignmentToArguments);
   7081 
   7082     // Handle the assignment.
   7083     switch (var->location()) {
   7084       case VariableLocation::GLOBAL:
   7085       case VariableLocation::UNALLOCATED:
   7086         CHECK_ALIVE(VisitForValue(expr->value()));
   7087         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
   7088                                        expr->AssignmentId());
   7089         return ast_context()->ReturnValue(Pop());
   7090 
   7091       case VariableLocation::PARAMETER:
   7092       case VariableLocation::LOCAL: {
   7093         // Perform an initialization check for let declared variables
   7094         // or parameters.
   7095         if (var->mode() == LET && expr->op() == Token::ASSIGN) {
   7096           HValue* env_value = environment()->Lookup(var);
   7097           if (env_value == graph()->GetConstantHole()) {
   7098             return Bailout(kAssignmentToLetVariableBeforeInitialization);
   7099           }
   7100         }
   7101         // We do not allow the arguments object to occur in a context where it
   7102         // may escape, but assignments to stack-allocated locals are
   7103         // permitted.
   7104         CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
   7105         HValue* value = Pop();
   7106         BindIfLive(var, value);
   7107         return ast_context()->ReturnValue(value);
   7108       }
   7109 
   7110       case VariableLocation::CONTEXT: {
   7111         // Bail out if we try to mutate a parameter value in a function using
   7112         // the arguments object.  We do not (yet) correctly handle the
   7113         // arguments property of the function.
   7114         if (current_info()->scope()->arguments() != NULL) {
   7115           // Parameters will rewrite to context slots.  We have no direct way
   7116           // to detect that the variable is a parameter.
   7117           int count = current_info()->scope()->num_parameters();
   7118           for (int i = 0; i < count; ++i) {
   7119             if (var == current_info()->scope()->parameter(i)) {
   7120               return Bailout(kAssignmentToParameterInArgumentsObject);
   7121             }
   7122           }
   7123         }
   7124 
   7125         CHECK_ALIVE(VisitForValue(expr->value()));
   7126         HStoreContextSlot::Mode mode;
   7127         if (expr->op() == Token::ASSIGN) {
   7128           switch (var->mode()) {
   7129             case LET:
   7130               mode = HStoreContextSlot::kCheckDeoptimize;
   7131               break;
   7132             case CONST:
   7133               // This case is checked statically so no need to
   7134               // perform checks here
   7135               UNREACHABLE();
   7136             case CONST_LEGACY:
   7137               return ast_context()->ReturnValue(Pop());
   7138             default:
   7139               mode = HStoreContextSlot::kNoCheck;
   7140           }
   7141         } else {
   7142           DCHECK_EQ(Token::INIT, expr->op());
   7143           if (var->mode() == CONST_LEGACY) {
   7144             mode = HStoreContextSlot::kCheckIgnoreAssignment;
   7145           } else {
   7146             mode = HStoreContextSlot::kNoCheck;
   7147           }
   7148         }
   7149 
   7150         HValue* context = BuildContextChainWalk(var);
   7151         HStoreContextSlot* instr = Add<HStoreContextSlot>(
   7152             context, var->index(), mode, Top());
   7153         if (instr->HasObservableSideEffects()) {
   7154           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   7155         }
   7156         return ast_context()->ReturnValue(Pop());
   7157       }
   7158 
   7159       case VariableLocation::LOOKUP:
   7160         return Bailout(kAssignmentToLOOKUPVariable);
   7161     }
   7162   } else {
   7163     return Bailout(kInvalidLeftHandSideInAssignment);
   7164   }
   7165 }
   7166 
   7167 
   7168 void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
   7169   // Generators are not optimized, so we should never get here.
   7170   UNREACHABLE();
   7171 }
   7172 
   7173 
   7174 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
   7175   DCHECK(!HasStackOverflow());
   7176   DCHECK(current_block() != NULL);
   7177   DCHECK(current_block()->HasPredecessor());
   7178   if (!ast_context()->IsEffect()) {
   7179     // The parser turns invalid left-hand sides in assignments into throw
   7180     // statements, which may not be in effect contexts. We might still try
   7181     // to optimize such functions; bail out now if we do.
   7182     return Bailout(kInvalidLeftHandSideInAssignment);
   7183   }
   7184   CHECK_ALIVE(VisitForValue(expr->exception()));
   7185 
   7186   HValue* value = environment()->Pop();
   7187   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
   7188   Add<HPushArguments>(value);
   7189   Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kThrow), 1);
   7190   Add<HSimulate>(expr->id());
   7191 
   7192   // If the throw definitely exits the function, we can finish with a dummy
   7193   // control flow at this point.  This is not the case if the throw is inside
   7194   // an inlined function which may be replaced.
   7195   if (call_context() == NULL) {
   7196     FinishExitCurrentBlock(New<HAbnormalExit>());
   7197   }
   7198 }
   7199 
   7200 
   7201 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
   7202   if (string->IsConstant()) {
   7203     HConstant* c_string = HConstant::cast(string);
   7204     if (c_string->HasStringValue()) {
   7205       return Add<HConstant>(c_string->StringValue()->map()->instance_type());
   7206     }
   7207   }
   7208   return Add<HLoadNamedField>(
   7209       Add<HLoadNamedField>(string, nullptr, HObjectAccess::ForMap()), nullptr,
   7210       HObjectAccess::ForMapInstanceType());
   7211 }
   7212 
   7213 
   7214 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
   7215   return AddInstruction(BuildLoadStringLength(string));
   7216 }
   7217 
   7218 
   7219 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* string) {
   7220   if (string->IsConstant()) {
   7221     HConstant* c_string = HConstant::cast(string);
   7222     if (c_string->HasStringValue()) {
   7223       return New<HConstant>(c_string->StringValue()->length());
   7224     }
   7225   }
   7226   return New<HLoadNamedField>(string, nullptr,
   7227                               HObjectAccess::ForStringLength());
   7228 }
   7229 
   7230 
   7231 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
   7232     PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
   7233     HValue* object, Handle<Name> name, HValue* value, bool is_uninitialized) {
   7234   if (is_uninitialized) {
   7235     Add<HDeoptimize>(
   7236         Deoptimizer::kInsufficientTypeFeedbackForGenericNamedAccess,
   7237         Deoptimizer::SOFT);
   7238   }
   7239   if (access_type == LOAD) {
   7240     Handle<TypeFeedbackVector> vector =
   7241         handle(current_feedback_vector(), isolate());
   7242 
   7243     if (!expr->AsProperty()->key()->IsPropertyName()) {
   7244       // It's possible that a keyed load of a constant string was converted
   7245       // to a named load. Here, at the last minute, we need to make sure to
   7246       // use a generic Keyed Load if we are using the type vector, because
   7247       // it has to share information with full code.
   7248       HConstant* key = Add<HConstant>(name);
   7249       HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
   7250           object, key, function_language_mode(), PREMONOMORPHIC);
   7251       result->SetVectorAndSlot(vector, slot);
   7252       return result;
   7253     }
   7254 
   7255     HLoadNamedGeneric* result = New<HLoadNamedGeneric>(
   7256         object, name, function_language_mode(), PREMONOMORPHIC);
   7257     result->SetVectorAndSlot(vector, slot);
   7258     return result;
   7259   } else {
   7260     if (current_feedback_vector()->GetKind(slot) ==
   7261         FeedbackVectorSlotKind::KEYED_STORE_IC) {
   7262       // It's possible that a keyed store of a constant string was converted
   7263       // to a named store. Here, at the last minute, we need to make sure to
   7264       // use a generic Keyed Store if we are using the type vector, because
   7265       // it has to share information with full code.
   7266       HConstant* key = Add<HConstant>(name);
   7267       HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
   7268           object, key, value, function_language_mode(), PREMONOMORPHIC);
   7269       Handle<TypeFeedbackVector> vector =
   7270           handle(current_feedback_vector(), isolate());
   7271       result->SetVectorAndSlot(vector, slot);
   7272       return result;
   7273     }
   7274 
   7275     HStoreNamedGeneric* result = New<HStoreNamedGeneric>(
   7276         object, name, value, function_language_mode(), PREMONOMORPHIC);
   7277     Handle<TypeFeedbackVector> vector =
   7278         handle(current_feedback_vector(), isolate());
   7279     result->SetVectorAndSlot(vector, slot);
   7280     return result;
   7281   }
   7282 }
   7283 
   7284 
   7285 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
   7286     PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
   7287     HValue* object, HValue* key, HValue* value) {
   7288   if (access_type == LOAD) {
   7289     InlineCacheState initial_state = expr->AsProperty()->GetInlineCacheState();
   7290     HLoadKeyedGeneric* result = New<HLoadKeyedGeneric>(
   7291         object, key, function_language_mode(), initial_state);
   7292     // HLoadKeyedGeneric with vector ics benefits from being encoded as
   7293     // MEGAMORPHIC because the vector/slot combo becomes unnecessary.
   7294     if (initial_state != MEGAMORPHIC) {
   7295       // We need to pass vector information.
   7296       Handle<TypeFeedbackVector> vector =
   7297           handle(current_feedback_vector(), isolate());
   7298       result->SetVectorAndSlot(vector, slot);
   7299     }
   7300     return result;
   7301   } else {
   7302     HStoreKeyedGeneric* result = New<HStoreKeyedGeneric>(
   7303         object, key, value, function_language_mode(), PREMONOMORPHIC);
   7304     Handle<TypeFeedbackVector> vector =
   7305         handle(current_feedback_vector(), isolate());
   7306     result->SetVectorAndSlot(vector, slot);
   7307     return result;
   7308   }
   7309 }
   7310 
   7311 
   7312 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
   7313   // Loads from a "stock" fast holey double arrays can elide the hole check.
   7314   // Loads from a "stock" fast holey array can convert the hole to undefined
   7315   // with impunity.
   7316   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
   7317   bool holey_double_elements =
   7318       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS);
   7319   bool holey_elements =
   7320       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_ELEMENTS);
   7321   if ((holey_double_elements || holey_elements) &&
   7322       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
   7323     load_mode =
   7324         holey_double_elements ? ALLOW_RETURN_HOLE : CONVERT_HOLE_TO_UNDEFINED;
   7325 
   7326     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
   7327     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
   7328     BuildCheckPrototypeMaps(prototype, object_prototype);
   7329     graph()->MarkDependsOnEmptyArrayProtoElements();
   7330   }
   7331   return load_mode;
   7332 }
   7333 
   7334 
   7335 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
   7336     HValue* object,
   7337     HValue* key,
   7338     HValue* val,
   7339     HValue* dependency,
   7340     Handle<Map> map,
   7341     PropertyAccessType access_type,
   7342     KeyedAccessStoreMode store_mode) {
   7343   HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
   7344 
   7345   if (access_type == STORE && map->prototype()->IsJSObject()) {
   7346     // monomorphic stores need a prototype chain check because shape
   7347     // changes could allow callbacks on elements in the chain that
   7348     // aren't compatible with monomorphic keyed stores.
   7349     PrototypeIterator iter(map);
   7350     JSObject* holder = NULL;
   7351     while (!iter.IsAtEnd()) {
   7352       // JSProxies can't occur here because we wouldn't have installed a
   7353       // non-generic IC if there were any.
   7354       holder = *PrototypeIterator::GetCurrent<JSObject>(iter);
   7355       iter.Advance();
   7356     }
   7357     DCHECK(holder && holder->IsJSObject());
   7358 
   7359     BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
   7360                             Handle<JSObject>(holder));
   7361   }
   7362 
   7363   LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
   7364   return BuildUncheckedMonomorphicElementAccess(
   7365       checked_object, key, val,
   7366       map->instance_type() == JS_ARRAY_TYPE,
   7367       map->elements_kind(), access_type,
   7368       load_mode, store_mode);
   7369 }
   7370 
   7371 
   7372 static bool CanInlineElementAccess(Handle<Map> map) {
   7373   return map->IsJSObjectMap() && !map->has_dictionary_elements() &&
   7374          !map->has_sloppy_arguments_elements() &&
   7375          !map->has_indexed_interceptor() && !map->is_access_check_needed();
   7376 }
   7377 
   7378 
   7379 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
   7380     HValue* object,
   7381     HValue* key,
   7382     HValue* val,
   7383     SmallMapList* maps) {
   7384   // For polymorphic loads of similar elements kinds (i.e. all tagged or all
   7385   // double), always use the "worst case" code without a transition.  This is
   7386   // much faster than transitioning the elements to the worst case, trading a
   7387   // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
   7388   bool has_double_maps = false;
   7389   bool has_smi_or_object_maps = false;
   7390   bool has_js_array_access = false;
   7391   bool has_non_js_array_access = false;
   7392   bool has_seen_holey_elements = false;
   7393   Handle<Map> most_general_consolidated_map;
   7394   for (int i = 0; i < maps->length(); ++i) {
   7395     Handle<Map> map = maps->at(i);
   7396     if (!CanInlineElementAccess(map)) return NULL;
   7397     // Don't allow mixing of JSArrays with JSObjects.
   7398     if (map->instance_type() == JS_ARRAY_TYPE) {
   7399       if (has_non_js_array_access) return NULL;
   7400       has_js_array_access = true;
   7401     } else if (has_js_array_access) {
   7402       return NULL;
   7403     } else {
   7404       has_non_js_array_access = true;
   7405     }
   7406     // Don't allow mixed, incompatible elements kinds.
   7407     if (map->has_fast_double_elements()) {
   7408       if (has_smi_or_object_maps) return NULL;
   7409       has_double_maps = true;
   7410     } else if (map->has_fast_smi_or_object_elements()) {
   7411       if (has_double_maps) return NULL;
   7412       has_smi_or_object_maps = true;
   7413     } else {
   7414       return NULL;
   7415     }
   7416     // Remember if we've ever seen holey elements.
   7417     if (IsHoleyElementsKind(map->elements_kind())) {
   7418       has_seen_holey_elements = true;
   7419     }
   7420     // Remember the most general elements kind, the code for its load will
   7421     // properly handle all of the more specific cases.
   7422     if ((i == 0) || IsMoreGeneralElementsKindTransition(
   7423             most_general_consolidated_map->elements_kind(),
   7424             map->elements_kind())) {
   7425       most_general_consolidated_map = map;
   7426     }
   7427   }
   7428   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
   7429 
   7430   HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
   7431   // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
   7432   // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
   7433   ElementsKind consolidated_elements_kind = has_seen_holey_elements
   7434       ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
   7435       : most_general_consolidated_map->elements_kind();
   7436   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
   7437   if (has_seen_holey_elements) {
   7438     // Make sure that all of the maps we are handling have the initial array
   7439     // prototype.
   7440     bool saw_non_array_prototype = false;
   7441     for (int i = 0; i < maps->length(); ++i) {
   7442       Handle<Map> map = maps->at(i);
   7443       if (map->prototype() != *isolate()->initial_array_prototype()) {
   7444         // We can't guarantee that loading the hole is safe. The prototype may
   7445         // have an element at this position.
   7446         saw_non_array_prototype = true;
   7447         break;
   7448       }
   7449     }
   7450 
   7451     if (!saw_non_array_prototype) {
   7452       Handle<Map> holey_map = handle(
   7453           isolate()->get_initial_js_array_map(consolidated_elements_kind));
   7454       load_mode = BuildKeyedHoleMode(holey_map);
   7455       if (load_mode != NEVER_RETURN_HOLE) {
   7456         for (int i = 0; i < maps->length(); ++i) {
   7457           Handle<Map> map = maps->at(i);
   7458           // The prototype check was already done for the holey map in
   7459           // BuildKeyedHoleMode.
   7460           if (!map.is_identical_to(holey_map)) {
   7461             Handle<JSObject> prototype(JSObject::cast(map->prototype()),
   7462                                        isolate());
   7463             Handle<JSObject> object_prototype =
   7464                 isolate()->initial_object_prototype();
   7465             BuildCheckPrototypeMaps(prototype, object_prototype);
   7466           }
   7467         }
   7468       }
   7469     }
   7470   }
   7471   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
   7472       checked_object, key, val,
   7473       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
   7474       consolidated_elements_kind, LOAD, load_mode, STANDARD_STORE);
   7475   return instr;
   7476 }
   7477 
   7478 
   7479 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
   7480     Expression* expr, FeedbackVectorSlot slot, HValue* object, HValue* key,
   7481     HValue* val, SmallMapList* maps, PropertyAccessType access_type,
   7482     KeyedAccessStoreMode store_mode, bool* has_side_effects) {
   7483   *has_side_effects = false;
   7484   BuildCheckHeapObject(object);
   7485 
   7486   if (access_type == LOAD) {
   7487     HInstruction* consolidated_load =
   7488         TryBuildConsolidatedElementLoad(object, key, val, maps);
   7489     if (consolidated_load != NULL) {
   7490       *has_side_effects |= consolidated_load->HasObservableSideEffects();
   7491       return consolidated_load;
   7492     }
   7493   }
   7494 
   7495   // Elements_kind transition support.
   7496   MapHandleList transition_target(maps->length());
   7497   // Collect possible transition targets.
   7498   MapHandleList possible_transitioned_maps(maps->length());
   7499   for (int i = 0; i < maps->length(); ++i) {
   7500     Handle<Map> map = maps->at(i);
   7501     // Loads from strings or loads with a mix of string and non-string maps
   7502     // shouldn't be handled polymorphically.
   7503     DCHECK(access_type != LOAD || !map->IsStringMap());
   7504     ElementsKind elements_kind = map->elements_kind();
   7505     if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) &&
   7506         elements_kind != GetInitialFastElementsKind()) {
   7507       possible_transitioned_maps.Add(map);
   7508     }
   7509     if (IsSloppyArgumentsElements(elements_kind)) {
   7510       HInstruction* result =
   7511           BuildKeyedGeneric(access_type, expr, slot, object, key, val);
   7512       *has_side_effects = result->HasObservableSideEffects();
   7513       return AddInstruction(result);
   7514     }
   7515   }
   7516   // Get transition target for each map (NULL == no transition).
   7517   for (int i = 0; i < maps->length(); ++i) {
   7518     Handle<Map> map = maps->at(i);
   7519     Handle<Map> transitioned_map =
   7520         Map::FindTransitionedMap(map, &possible_transitioned_maps);
   7521     transition_target.Add(transitioned_map);
   7522   }
   7523 
   7524   MapHandleList untransitionable_maps(maps->length());
   7525   HTransitionElementsKind* transition = NULL;
   7526   for (int i = 0; i < maps->length(); ++i) {
   7527     Handle<Map> map = maps->at(i);
   7528     DCHECK(map->IsMap());
   7529     if (!transition_target.at(i).is_null()) {
   7530       DCHECK(Map::IsValidElementsTransition(
   7531           map->elements_kind(),
   7532           transition_target.at(i)->elements_kind()));
   7533       transition = Add<HTransitionElementsKind>(object, map,
   7534                                                 transition_target.at(i));
   7535     } else {
   7536       untransitionable_maps.Add(map);
   7537     }
   7538   }
   7539 
   7540   // If only one map is left after transitioning, handle this case
   7541   // monomorphically.
   7542   DCHECK(untransitionable_maps.length() >= 1);
   7543   if (untransitionable_maps.length() == 1) {
   7544     Handle<Map> untransitionable_map = untransitionable_maps[0];
   7545     HInstruction* instr = NULL;
   7546     if (!CanInlineElementAccess(untransitionable_map)) {
   7547       instr = AddInstruction(
   7548           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
   7549     } else {
   7550       instr = BuildMonomorphicElementAccess(
   7551           object, key, val, transition, untransitionable_map, access_type,
   7552           store_mode);
   7553     }
   7554     *has_side_effects |= instr->HasObservableSideEffects();
   7555     return access_type == STORE ? val : instr;
   7556   }
   7557 
   7558   HBasicBlock* join = graph()->CreateBasicBlock();
   7559 
   7560   for (int i = 0; i < untransitionable_maps.length(); ++i) {
   7561     Handle<Map> map = untransitionable_maps[i];
   7562     ElementsKind elements_kind = map->elements_kind();
   7563     HBasicBlock* this_map = graph()->CreateBasicBlock();
   7564     HBasicBlock* other_map = graph()->CreateBasicBlock();
   7565     HCompareMap* mapcompare =
   7566         New<HCompareMap>(object, map, this_map, other_map);
   7567     FinishCurrentBlock(mapcompare);
   7568 
   7569     set_current_block(this_map);
   7570     HInstruction* access = NULL;
   7571     if (!CanInlineElementAccess(map)) {
   7572       access = AddInstruction(
   7573           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
   7574     } else {
   7575       DCHECK(IsFastElementsKind(elements_kind) ||
   7576              IsFixedTypedArrayElementsKind(elements_kind));
   7577       LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
   7578       // Happily, mapcompare is a checked object.
   7579       access = BuildUncheckedMonomorphicElementAccess(
   7580           mapcompare, key, val,
   7581           map->instance_type() == JS_ARRAY_TYPE,
   7582           elements_kind, access_type,
   7583           load_mode,
   7584           store_mode);
   7585     }
   7586     *has_side_effects |= access->HasObservableSideEffects();
   7587     // The caller will use has_side_effects and add a correct Simulate.
   7588     access->SetFlag(HValue::kHasNoObservableSideEffects);
   7589     if (access_type == LOAD) {
   7590       Push(access);
   7591     }
   7592     NoObservableSideEffectsScope scope(this);
   7593     GotoNoSimulate(join);
   7594     set_current_block(other_map);
   7595   }
   7596 
   7597   // Ensure that we visited at least one map above that goes to join. This is
   7598   // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
   7599   // rather than joining the join block. If this becomes an issue, insert a
   7600   // generic access in the case length() == 0.
   7601   DCHECK(join->predecessors()->length() > 0);
   7602   // Deopt if none of the cases matched.
   7603   NoObservableSideEffectsScope scope(this);
   7604   FinishExitWithHardDeoptimization(
   7605       Deoptimizer::kUnknownMapInPolymorphicElementAccess);
   7606   set_current_block(join);
   7607   return access_type == STORE ? val : Pop();
   7608 }
   7609 
   7610 
   7611 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
   7612     HValue* obj, HValue* key, HValue* val, Expression* expr,
   7613     FeedbackVectorSlot slot, BailoutId ast_id, BailoutId return_id,
   7614     PropertyAccessType access_type, bool* has_side_effects) {
   7615   // A keyed name access with type feedback may contain the name.
   7616   Handle<TypeFeedbackVector> vector =
   7617       handle(current_feedback_vector(), isolate());
   7618   HValue* expected_key = key;
   7619   if (!key->ActualValue()->IsConstant()) {
   7620     Name* name = nullptr;
   7621     if (access_type == LOAD) {
   7622       KeyedLoadICNexus nexus(vector, slot);
   7623       name = nexus.FindFirstName();
   7624     } else {
   7625       KeyedStoreICNexus nexus(vector, slot);
   7626       name = nexus.FindFirstName();
   7627     }
   7628     if (name != nullptr) {
   7629       Handle<Name> handle_name(name);
   7630       expected_key = Add<HConstant>(handle_name);
   7631       // We need a check against the key.
   7632       bool in_new_space = isolate()->heap()->InNewSpace(*handle_name);
   7633       Unique<Name> unique_name = Unique<Name>::CreateUninitialized(handle_name);
   7634       Add<HCheckValue>(key, unique_name, in_new_space);
   7635     }
   7636   }
   7637   if (expected_key->ActualValue()->IsConstant()) {
   7638     Handle<Object> constant =
   7639         HConstant::cast(expected_key->ActualValue())->handle(isolate());
   7640     uint32_t array_index;
   7641     if ((constant->IsString() &&
   7642          !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) ||
   7643         constant->IsSymbol()) {
   7644       if (!constant->IsUniqueName()) {
   7645         constant = isolate()->factory()->InternalizeString(
   7646             Handle<String>::cast(constant));
   7647       }
   7648       HValue* access =
   7649           BuildNamedAccess(access_type, ast_id, return_id, expr, slot, obj,
   7650                            Handle<Name>::cast(constant), val, false);
   7651       if (access == NULL || access->IsPhi() ||
   7652           HInstruction::cast(access)->IsLinked()) {
   7653         *has_side_effects = false;
   7654       } else {
   7655         HInstruction* instr = HInstruction::cast(access);
   7656         AddInstruction(instr);
   7657         *has_side_effects = instr->HasObservableSideEffects();
   7658       }
   7659       return access;
   7660     }
   7661   }
   7662 
   7663   DCHECK(!expr->IsPropertyName());
   7664   HInstruction* instr = NULL;
   7665 
   7666   SmallMapList* maps;
   7667   bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, zone());
   7668 
   7669   bool force_generic = false;
   7670   if (expr->GetKeyType() == PROPERTY) {
   7671     // Non-Generic accesses assume that elements are being accessed, and will
   7672     // deopt for non-index keys, which the IC knows will occur.
   7673     // TODO(jkummerow): Consider adding proper support for property accesses.
   7674     force_generic = true;
   7675     monomorphic = false;
   7676   } else if (access_type == STORE &&
   7677              (monomorphic || (maps != NULL && !maps->is_empty()))) {
   7678     // Stores can't be mono/polymorphic if their prototype chain has dictionary
   7679     // elements. However a receiver map that has dictionary elements itself
   7680     // should be left to normal mono/poly behavior (the other maps may benefit
   7681     // from highly optimized stores).
   7682     for (int i = 0; i < maps->length(); i++) {
   7683       Handle<Map> current_map = maps->at(i);
   7684       if (current_map->DictionaryElementsInPrototypeChainOnly()) {
   7685         force_generic = true;
   7686         monomorphic = false;
   7687         break;
   7688       }
   7689     }
   7690   } else if (access_type == LOAD && !monomorphic &&
   7691              (maps != NULL && !maps->is_empty())) {
   7692     // Polymorphic loads have to go generic if any of the maps are strings.
   7693     // If some, but not all of the maps are strings, we should go generic
   7694     // because polymorphic access wants to key on ElementsKind and isn't
   7695     // compatible with strings.
   7696     for (int i = 0; i < maps->length(); i++) {
   7697       Handle<Map> current_map = maps->at(i);
   7698       if (current_map->IsStringMap()) {
   7699         force_generic = true;
   7700         break;
   7701       }
   7702     }
   7703   }
   7704 
   7705   if (monomorphic) {
   7706     Handle<Map> map = maps->first();
   7707     if (!CanInlineElementAccess(map)) {
   7708       instr = AddInstruction(
   7709           BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
   7710     } else {
   7711       BuildCheckHeapObject(obj);
   7712       instr = BuildMonomorphicElementAccess(
   7713           obj, key, val, NULL, map, access_type, expr->GetStoreMode());
   7714     }
   7715   } else if (!force_generic && (maps != NULL && !maps->is_empty())) {
   7716     return HandlePolymorphicElementAccess(expr, slot, obj, key, val, maps,
   7717                                           access_type, expr->GetStoreMode(),
   7718                                           has_side_effects);
   7719   } else {
   7720     if (access_type == STORE) {
   7721       if (expr->IsAssignment() &&
   7722           expr->AsAssignment()->HasNoTypeInformation()) {
   7723         Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedStore,
   7724                          Deoptimizer::SOFT);
   7725       }
   7726     } else {
   7727       if (expr->AsProperty()->HasNoTypeInformation()) {
   7728         Add<HDeoptimize>(Deoptimizer::kInsufficientTypeFeedbackForKeyedLoad,
   7729                          Deoptimizer::SOFT);
   7730       }
   7731     }
   7732     instr = AddInstruction(
   7733         BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
   7734   }
   7735   *has_side_effects = instr->HasObservableSideEffects();
   7736   return instr;
   7737 }
   7738 
   7739 
   7740 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
   7741   // Outermost function already has arguments on the stack.
   7742   if (function_state()->outer() == NULL) return;
   7743 
   7744   if (function_state()->arguments_pushed()) return;
   7745 
   7746   // Push arguments when entering inlined function.
   7747   HEnterInlined* entry = function_state()->entry();
   7748   entry->set_arguments_pushed();
   7749 
   7750   HArgumentsObject* arguments = entry->arguments_object();
   7751   const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
   7752 
   7753   HInstruction* insert_after = entry;
   7754   for (int i = 0; i < arguments_values->length(); i++) {
   7755     HValue* argument = arguments_values->at(i);
   7756     HInstruction* push_argument = New<HPushArguments>(argument);
   7757     push_argument->InsertAfter(insert_after);
   7758     insert_after = push_argument;
   7759   }
   7760 
   7761   HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
   7762   arguments_elements->ClearFlag(HValue::kUseGVN);
   7763   arguments_elements->InsertAfter(insert_after);
   7764   function_state()->set_arguments_elements(arguments_elements);
   7765 }
   7766 
   7767 
   7768 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
   7769   VariableProxy* proxy = expr->obj()->AsVariableProxy();
   7770   if (proxy == NULL) return false;
   7771   if (!proxy->var()->IsStackAllocated()) return false;
   7772   if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
   7773     return false;
   7774   }
   7775 
   7776   HInstruction* result = NULL;
   7777   if (expr->key()->IsPropertyName()) {
   7778     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
   7779     if (!String::Equals(name, isolate()->factory()->length_string())) {
   7780       return false;
   7781     }
   7782 
   7783     if (function_state()->outer() == NULL) {
   7784       HInstruction* elements = Add<HArgumentsElements>(false);
   7785       result = New<HArgumentsLength>(elements);
   7786     } else {
   7787       // Number of arguments without receiver.
   7788       int argument_count = environment()->
   7789           arguments_environment()->parameter_count() - 1;
   7790       result = New<HConstant>(argument_count);
   7791     }
   7792   } else {
   7793     Push(graph()->GetArgumentsObject());
   7794     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
   7795     HValue* key = Pop();
   7796     Drop(1);  // Arguments object.
   7797     if (function_state()->outer() == NULL) {
   7798       HInstruction* elements = Add<HArgumentsElements>(false);
   7799       HInstruction* length = Add<HArgumentsLength>(elements);
   7800       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
   7801       result = New<HAccessArgumentsAt>(elements, length, checked_key);
   7802     } else {
   7803       EnsureArgumentsArePushedForAccess();
   7804 
   7805       // Number of arguments without receiver.
   7806       HInstruction* elements = function_state()->arguments_elements();
   7807       int argument_count = environment()->
   7808           arguments_environment()->parameter_count() - 1;
   7809       HInstruction* length = Add<HConstant>(argument_count);
   7810       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
   7811       result = New<HAccessArgumentsAt>(elements, length, checked_key);
   7812     }
   7813   }
   7814   ast_context()->ReturnInstruction(result, expr->id());
   7815   return true;
   7816 }
   7817 
   7818 
   7819 HValue* HOptimizedGraphBuilder::BuildNamedAccess(
   7820     PropertyAccessType access, BailoutId ast_id, BailoutId return_id,
   7821     Expression* expr, FeedbackVectorSlot slot, HValue* object,
   7822     Handle<Name> name, HValue* value, bool is_uninitialized) {
   7823   SmallMapList* maps;
   7824   ComputeReceiverTypes(expr, object, &maps, zone());
   7825   DCHECK(maps != NULL);
   7826 
   7827   if (maps->length() > 0) {
   7828     PropertyAccessInfo info(this, access, maps->first(), name);
   7829     if (!info.CanAccessAsMonomorphic(maps)) {
   7830       HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id,
   7831                                         object, value, maps, name);
   7832       return NULL;
   7833     }
   7834 
   7835     HValue* checked_object;
   7836     // Type::Number() is only supported by polymorphic load/call handling.
   7837     DCHECK(!info.IsNumberType());
   7838     BuildCheckHeapObject(object);
   7839     if (AreStringTypes(maps)) {
   7840       checked_object =
   7841           Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
   7842     } else {
   7843       checked_object = Add<HCheckMaps>(object, maps);
   7844     }
   7845     return BuildMonomorphicAccess(
   7846         &info, object, checked_object, value, ast_id, return_id);
   7847   }
   7848 
   7849   return BuildNamedGeneric(access, expr, slot, object, name, value,
   7850                            is_uninitialized);
   7851 }
   7852 
   7853 
   7854 void HOptimizedGraphBuilder::PushLoad(Property* expr,
   7855                                       HValue* object,
   7856                                       HValue* key) {
   7857   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
   7858   Push(object);
   7859   if (key != NULL) Push(key);
   7860   BuildLoad(expr, expr->LoadId());
   7861 }
   7862 
   7863 
   7864 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
   7865                                        BailoutId ast_id) {
   7866   HInstruction* instr = NULL;
   7867   if (expr->IsStringAccess() && expr->GetKeyType() == ELEMENT) {
   7868     HValue* index = Pop();
   7869     HValue* string = Pop();
   7870     HInstruction* char_code = BuildStringCharCodeAt(string, index);
   7871     AddInstruction(char_code);
   7872     instr = NewUncasted<HStringCharFromCode>(char_code);
   7873 
   7874   } else if (expr->key()->IsPropertyName()) {
   7875     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
   7876     HValue* object = Pop();
   7877 
   7878     HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
   7879                                      expr->PropertyFeedbackSlot(), object, name,
   7880                                      NULL, expr->IsUninitialized());
   7881     if (value == NULL) return;
   7882     if (value->IsPhi()) return ast_context()->ReturnValue(value);
   7883     instr = HInstruction::cast(value);
   7884     if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
   7885 
   7886   } else {
   7887     HValue* key = Pop();
   7888     HValue* obj = Pop();
   7889 
   7890     bool has_side_effects = false;
   7891     HValue* load = HandleKeyedElementAccess(
   7892         obj, key, NULL, expr, expr->PropertyFeedbackSlot(), ast_id,
   7893         expr->LoadId(), LOAD, &has_side_effects);
   7894     if (has_side_effects) {
   7895       if (ast_context()->IsEffect()) {
   7896         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   7897       } else {
   7898         Push(load);
   7899         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   7900         Drop(1);
   7901       }
   7902     }
   7903     if (load == NULL) return;
   7904     return ast_context()->ReturnValue(load);
   7905   }
   7906   return ast_context()->ReturnInstruction(instr, ast_id);
   7907 }
   7908 
   7909 
   7910 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
   7911   DCHECK(!HasStackOverflow());
   7912   DCHECK(current_block() != NULL);
   7913   DCHECK(current_block()->HasPredecessor());
   7914 
   7915   if (TryArgumentsAccess(expr)) return;
   7916 
   7917   CHECK_ALIVE(VisitForValue(expr->obj()));
   7918   if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
   7919     CHECK_ALIVE(VisitForValue(expr->key()));
   7920   }
   7921 
   7922   BuildLoad(expr, expr->id());
   7923 }
   7924 
   7925 
   7926 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) {
   7927   HCheckMaps* check = Add<HCheckMaps>(
   7928       Add<HConstant>(constant), handle(constant->map()));
   7929   check->ClearDependsOnFlag(kElementsKind);
   7930   return check;
   7931 }
   7932 
   7933 
   7934 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
   7935                                                      Handle<JSObject> holder) {
   7936   PrototypeIterator iter(isolate(), prototype,
   7937                          PrototypeIterator::START_AT_RECEIVER);
   7938   while (holder.is_null() ||
   7939          !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
   7940     BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
   7941     iter.Advance();
   7942     if (iter.IsAtEnd()) {
   7943       return NULL;
   7944     }
   7945   }
   7946   return BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
   7947 }
   7948 
   7949 
   7950 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
   7951                                                    Handle<Map> receiver_map) {
   7952   if (!holder.is_null()) {
   7953     Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
   7954     BuildCheckPrototypeMaps(prototype, holder);
   7955   }
   7956 }
   7957 
   7958 
   7959 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(HValue* fun,
   7960                                                            int argument_count) {
   7961   return New<HCallJSFunction>(fun, argument_count);
   7962 }
   7963 
   7964 
   7965 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall(
   7966     HValue* fun, HValue* context,
   7967     int argument_count, HValue* expected_param_count) {
   7968   HValue* new_target = graph()->GetConstantUndefined();
   7969   HValue* arity = Add<HConstant>(argument_count - 1);
   7970 
   7971   HValue* op_vals[] = {context, fun, new_target, arity, expected_param_count};
   7972 
   7973   Callable callable = CodeFactory::ArgumentAdaptor(isolate());
   7974   HConstant* stub = Add<HConstant>(callable.code());
   7975 
   7976   return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
   7977                                   Vector<HValue*>(op_vals, arraysize(op_vals)));
   7978 }
   7979 
   7980 
   7981 HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction(
   7982     Handle<JSFunction> jsfun, int argument_count) {
   7983   HValue* target = Add<HConstant>(jsfun);
   7984   // For constant functions, we try to avoid calling the
   7985   // argument adaptor and instead call the function directly
   7986   int formal_parameter_count =
   7987       jsfun->shared()->internal_formal_parameter_count();
   7988   bool dont_adapt_arguments =
   7989       (formal_parameter_count ==
   7990        SharedFunctionInfo::kDontAdaptArgumentsSentinel);
   7991   int arity = argument_count - 1;
   7992   bool can_invoke_directly =
   7993       dont_adapt_arguments || formal_parameter_count == arity;
   7994   if (can_invoke_directly) {
   7995     if (jsfun.is_identical_to(current_info()->closure())) {
   7996       graph()->MarkRecursive();
   7997     }
   7998     return NewPlainFunctionCall(target, argument_count);
   7999   } else {
   8000     HValue* param_count_value = Add<HConstant>(formal_parameter_count);
   8001     HValue* context = Add<HLoadNamedField>(
   8002         target, nullptr, HObjectAccess::ForFunctionContextPointer());
   8003     return NewArgumentAdaptorCall(target, context,
   8004         argument_count, param_count_value);
   8005   }
   8006   UNREACHABLE();
   8007   return NULL;
   8008 }
   8009 
   8010 
   8011 class FunctionSorter {
   8012  public:
   8013   explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
   8014       : index_(index), ticks_(ticks), size_(size) {}
   8015 
   8016   int index() const { return index_; }
   8017   int ticks() const { return ticks_; }
   8018   int size() const { return size_; }
   8019 
   8020  private:
   8021   int index_;
   8022   int ticks_;
   8023   int size_;
   8024 };
   8025 
   8026 
   8027 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
   8028   int diff = lhs.ticks() - rhs.ticks();
   8029   if (diff != 0) return diff > 0;
   8030   return lhs.size() < rhs.size();
   8031 }
   8032 
   8033 
   8034 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
   8035                                                         HValue* receiver,
   8036                                                         SmallMapList* maps,
   8037                                                         Handle<String> name) {
   8038   int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
   8039   FunctionSorter order[kMaxCallPolymorphism];
   8040 
   8041   bool handle_smi = false;
   8042   bool handled_string = false;
   8043   int ordered_functions = 0;
   8044 
   8045   int i;
   8046   for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism;
   8047        ++i) {
   8048     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
   8049     if (info.CanAccessMonomorphic() && info.IsDataConstant() &&
   8050         info.constant()->IsJSFunction()) {
   8051       if (info.IsStringType()) {
   8052         if (handled_string) continue;
   8053         handled_string = true;
   8054       }
   8055       Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
   8056       if (info.IsNumberType()) {
   8057         handle_smi = true;
   8058       }
   8059       expr->set_target(target);
   8060       order[ordered_functions++] = FunctionSorter(
   8061           i, target->shared()->profiler_ticks(), InliningAstSize(target));
   8062     }
   8063   }
   8064 
   8065   std::sort(order, order + ordered_functions);
   8066 
   8067   if (i < maps->length()) {
   8068     maps->Clear();
   8069     ordered_functions = -1;
   8070   }
   8071 
   8072   HBasicBlock* number_block = NULL;
   8073   HBasicBlock* join = NULL;
   8074   handled_string = false;
   8075   int count = 0;
   8076 
   8077   for (int fn = 0; fn < ordered_functions; ++fn) {
   8078     int i = order[fn].index();
   8079     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
   8080     if (info.IsStringType()) {
   8081       if (handled_string) continue;
   8082       handled_string = true;
   8083     }
   8084     // Reloads the target.
   8085     info.CanAccessMonomorphic();
   8086     Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
   8087 
   8088     expr->set_target(target);
   8089     if (count == 0) {
   8090       // Only needed once.
   8091       join = graph()->CreateBasicBlock();
   8092       if (handle_smi) {
   8093         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
   8094         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
   8095         number_block = graph()->CreateBasicBlock();
   8096         FinishCurrentBlock(New<HIsSmiAndBranch>(
   8097                 receiver, empty_smi_block, not_smi_block));
   8098         GotoNoSimulate(empty_smi_block, number_block);
   8099         set_current_block(not_smi_block);
   8100       } else {
   8101         BuildCheckHeapObject(receiver);
   8102       }
   8103     }
   8104     ++count;
   8105     HBasicBlock* if_true = graph()->CreateBasicBlock();
   8106     HBasicBlock* if_false = graph()->CreateBasicBlock();
   8107     HUnaryControlInstruction* compare;
   8108 
   8109     Handle<Map> map = info.map();
   8110     if (info.IsNumberType()) {
   8111       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
   8112       compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
   8113     } else if (info.IsStringType()) {
   8114       compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
   8115     } else {
   8116       compare = New<HCompareMap>(receiver, map, if_true, if_false);
   8117     }
   8118     FinishCurrentBlock(compare);
   8119 
   8120     if (info.IsNumberType()) {
   8121       GotoNoSimulate(if_true, number_block);
   8122       if_true = number_block;
   8123     }
   8124 
   8125     set_current_block(if_true);
   8126 
   8127     AddCheckPrototypeMaps(info.holder(), map);
   8128 
   8129     HValue* function = Add<HConstant>(expr->target());
   8130     environment()->SetExpressionStackAt(0, function);
   8131     Push(receiver);
   8132     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   8133     bool needs_wrapping = info.NeedsWrappingFor(target);
   8134     bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
   8135     if (FLAG_trace_inlining && try_inline) {
   8136       Handle<JSFunction> caller = current_info()->closure();
   8137       base::SmartArrayPointer<char> caller_name =
   8138           caller->shared()->DebugName()->ToCString();
   8139       PrintF("Trying to inline the polymorphic call to %s from %s\n",
   8140              name->ToCString().get(),
   8141              caller_name.get());
   8142     }
   8143     if (try_inline && TryInlineCall(expr)) {
   8144       // Trying to inline will signal that we should bailout from the
   8145       // entire compilation by setting stack overflow on the visitor.
   8146       if (HasStackOverflow()) return;
   8147     } else {
   8148       // Since HWrapReceiver currently cannot actually wrap numbers and strings,
   8149       // use the regular CallFunctionStub for method calls to wrap the receiver.
   8150       // TODO(verwaest): Support creation of value wrappers directly in
   8151       // HWrapReceiver.
   8152       HInstruction* call =
   8153           needs_wrapping ? NewUncasted<HCallFunction>(
   8154                                function, argument_count,
   8155                                ConvertReceiverMode::kNotNullOrUndefined)
   8156                          : BuildCallConstantFunction(target, argument_count);
   8157       PushArgumentsFromEnvironment(argument_count);
   8158       AddInstruction(call);
   8159       Drop(1);  // Drop the function.
   8160       if (!ast_context()->IsEffect()) Push(call);
   8161     }
   8162 
   8163     if (current_block() != NULL) Goto(join);
   8164     set_current_block(if_false);
   8165   }
   8166 
   8167   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
   8168   // know about and do not want to handle ones we've never seen.  Otherwise
   8169   // use a generic IC.
   8170   if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) {
   8171     FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall);
   8172   } else {
   8173     Property* prop = expr->expression()->AsProperty();
   8174     HInstruction* function =
   8175         BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver,
   8176                           name, NULL, prop->IsUninitialized());
   8177     AddInstruction(function);
   8178     Push(function);
   8179     AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
   8180 
   8181     environment()->SetExpressionStackAt(1, function);
   8182     environment()->SetExpressionStackAt(0, receiver);
   8183     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   8184 
   8185     HInstruction* call = New<HCallFunction>(
   8186         function, argument_count, ConvertReceiverMode::kNotNullOrUndefined);
   8187 
   8188     PushArgumentsFromEnvironment(argument_count);
   8189 
   8190     Drop(1);  // Function.
   8191 
   8192     if (join != NULL) {
   8193       AddInstruction(call);
   8194       if (!ast_context()->IsEffect()) Push(call);
   8195       Goto(join);
   8196     } else {
   8197       return ast_context()->ReturnInstruction(call, expr->id());
   8198     }
   8199   }
   8200 
   8201   // We assume that control flow is always live after an expression.  So
   8202   // even without predecessors to the join block, we set it as the exit
   8203   // block and continue by adding instructions there.
   8204   DCHECK(join != NULL);
   8205   if (join->HasPredecessor()) {
   8206     set_current_block(join);
   8207     join->SetJoinId(expr->id());
   8208     if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
   8209   } else {
   8210     set_current_block(NULL);
   8211   }
   8212 }
   8213 
   8214 
   8215 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
   8216                                          Handle<JSFunction> caller,
   8217                                          const char* reason) {
   8218   if (FLAG_trace_inlining) {
   8219     base::SmartArrayPointer<char> target_name =
   8220         target->shared()->DebugName()->ToCString();
   8221     base::SmartArrayPointer<char> caller_name =
   8222         caller->shared()->DebugName()->ToCString();
   8223     if (reason == NULL) {
   8224       PrintF("Inlined %s called from %s.\n", target_name.get(),
   8225              caller_name.get());
   8226     } else {
   8227       PrintF("Did not inline %s called from %s (%s).\n",
   8228              target_name.get(), caller_name.get(), reason);
   8229     }
   8230   }
   8231 }
   8232 
   8233 
   8234 static const int kNotInlinable = 1000000000;
   8235 
   8236 
   8237 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
   8238   if (!FLAG_use_inlining) return kNotInlinable;
   8239 
   8240   // Precondition: call is monomorphic and we have found a target with the
   8241   // appropriate arity.
   8242   Handle<JSFunction> caller = current_info()->closure();
   8243   Handle<SharedFunctionInfo> target_shared(target->shared());
   8244 
   8245   // Always inline functions that force inlining.
   8246   if (target_shared->force_inline()) {
   8247     return 0;
   8248   }
   8249   if (target->shared()->IsBuiltin()) {
   8250     return kNotInlinable;
   8251   }
   8252 
   8253   if (target_shared->IsApiFunction()) {
   8254     TraceInline(target, caller, "target is api function");
   8255     return kNotInlinable;
   8256   }
   8257 
   8258   // Do a quick check on source code length to avoid parsing large
   8259   // inlining candidates.
   8260   if (target_shared->SourceSize() >
   8261       Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
   8262     TraceInline(target, caller, "target text too big");
   8263     return kNotInlinable;
   8264   }
   8265 
   8266   // Target must be inlineable.
   8267   BailoutReason noopt_reason = target_shared->disable_optimization_reason();
   8268   if (!target_shared->IsInlineable() && noopt_reason != kHydrogenFilter) {
   8269     TraceInline(target, caller, "target not inlineable");
   8270     return kNotInlinable;
   8271   }
   8272   if (noopt_reason != kNoReason && noopt_reason != kHydrogenFilter) {
   8273     TraceInline(target, caller, "target contains unsupported syntax [early]");
   8274     return kNotInlinable;
   8275   }
   8276 
   8277   int nodes_added = target_shared->ast_node_count();
   8278   return nodes_added;
   8279 }
   8280 
   8281 
   8282 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
   8283                                        int arguments_count,
   8284                                        HValue* implicit_return_value,
   8285                                        BailoutId ast_id, BailoutId return_id,
   8286                                        InliningKind inlining_kind) {
   8287   if (target->context()->native_context() !=
   8288       top_info()->closure()->context()->native_context()) {
   8289     return false;
   8290   }
   8291   int nodes_added = InliningAstSize(target);
   8292   if (nodes_added == kNotInlinable) return false;
   8293 
   8294   Handle<JSFunction> caller = current_info()->closure();
   8295 
   8296   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
   8297     TraceInline(target, caller, "target AST is too large [early]");
   8298     return false;
   8299   }
   8300 
   8301   // Don't inline deeper than the maximum number of inlining levels.
   8302   HEnvironment* env = environment();
   8303   int current_level = 1;
   8304   while (env->outer() != NULL) {
   8305     if (current_level == FLAG_max_inlining_levels) {
   8306       TraceInline(target, caller, "inline depth limit reached");
   8307       return false;
   8308     }
   8309     if (env->outer()->frame_type() == JS_FUNCTION) {
   8310       current_level++;
   8311     }
   8312     env = env->outer();
   8313   }
   8314 
   8315   // Don't inline recursive functions.
   8316   for (FunctionState* state = function_state();
   8317        state != NULL;
   8318        state = state->outer()) {
   8319     if (*state->compilation_info()->closure() == *target) {
   8320       TraceInline(target, caller, "target is recursive");
   8321       return false;
   8322     }
   8323   }
   8324 
   8325   // We don't want to add more than a certain number of nodes from inlining.
   8326   // Always inline small methods (<= 10 nodes).
   8327   if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
   8328                            kUnlimitedMaxInlinedNodesCumulative)) {
   8329     TraceInline(target, caller, "cumulative AST node limit reached");
   8330     return false;
   8331   }
   8332 
   8333   // Parse and allocate variables.
   8334   // Use the same AstValueFactory for creating strings in the sub-compilation
   8335   // step, but don't transfer ownership to target_info.
   8336   ParseInfo parse_info(zone(), target);
   8337   parse_info.set_ast_value_factory(
   8338       top_info()->parse_info()->ast_value_factory());
   8339   parse_info.set_ast_value_factory_owned(false);
   8340 
   8341   CompilationInfo target_info(&parse_info);
   8342   Handle<SharedFunctionInfo> target_shared(target->shared());
   8343 
   8344   if (IsClassConstructor(target_shared->kind())) {
   8345     TraceInline(target, caller, "target is classConstructor");
   8346     return false;
   8347   }
   8348   if (target_shared->HasDebugInfo()) {
   8349     TraceInline(target, caller, "target is being debugged");
   8350     return false;
   8351   }
   8352   if (!Compiler::ParseAndAnalyze(target_info.parse_info())) {
   8353     if (target_info.isolate()->has_pending_exception()) {
   8354       // Parse or scope error, never optimize this function.
   8355       SetStackOverflow();
   8356       target_shared->DisableOptimization(kParseScopeError);
   8357     }
   8358     TraceInline(target, caller, "parse failure");
   8359     return false;
   8360   }
   8361 
   8362   if (target_info.scope()->num_heap_slots() > 0) {
   8363     TraceInline(target, caller, "target has context-allocated variables");
   8364     return false;
   8365   }
   8366 
   8367   int rest_index;
   8368   Variable* rest = target_info.scope()->rest_parameter(&rest_index);
   8369   if (rest) {
   8370     TraceInline(target, caller, "target uses rest parameters");
   8371     return false;
   8372   }
   8373 
   8374   FunctionLiteral* function = target_info.literal();
   8375 
   8376   // The following conditions must be checked again after re-parsing, because
   8377   // earlier the information might not have been complete due to lazy parsing.
   8378   nodes_added = function->ast_node_count();
   8379   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
   8380     TraceInline(target, caller, "target AST is too large [late]");
   8381     return false;
   8382   }
   8383   if (function->dont_optimize()) {
   8384     TraceInline(target, caller, "target contains unsupported syntax [late]");
   8385     return false;
   8386   }
   8387 
   8388   // If the function uses the arguments object check that inlining of functions
   8389   // with arguments object is enabled and the arguments-variable is
   8390   // stack allocated.
   8391   if (function->scope()->arguments() != NULL) {
   8392     if (!FLAG_inline_arguments) {
   8393       TraceInline(target, caller, "target uses arguments object");
   8394       return false;
   8395     }
   8396   }
   8397 
   8398   // Unsupported variable references present.
   8399   if (function->scope()->this_function_var() != nullptr ||
   8400       function->scope()->new_target_var() != nullptr) {
   8401     TraceInline(target, caller, "target uses new target or this function");
   8402     return false;
   8403   }
   8404 
   8405   // All declarations must be inlineable.
   8406   ZoneList<Declaration*>* decls = target_info.scope()->declarations();
   8407   int decl_count = decls->length();
   8408   for (int i = 0; i < decl_count; ++i) {
   8409     if (!decls->at(i)->IsInlineable()) {
   8410       TraceInline(target, caller, "target has non-trivial declaration");
   8411       return false;
   8412     }
   8413   }
   8414 
   8415   // In strong mode it is an error to call a function with too few arguments.
   8416   // In that case do not inline because then the arity check would be skipped.
   8417   if (is_strong(function->language_mode()) &&
   8418       arguments_count < function->parameter_count()) {
   8419     TraceInline(target, caller,
   8420                 "too few arguments passed to a strong function");
   8421     return false;
   8422   }
   8423 
   8424   // Generate the deoptimization data for the unoptimized version of
   8425   // the target function if we don't already have it.
   8426   if (!Compiler::EnsureDeoptimizationSupport(&target_info)) {
   8427     TraceInline(target, caller, "could not generate deoptimization info");
   8428     return false;
   8429   }
   8430   // Remember that we inlined this function. This needs to be called right
   8431   // after the EnsureDeoptimizationSupport call so that the code flusher
   8432   // does not remove the code with the deoptimization support.
   8433   top_info()->AddInlinedFunction(target_info.shared_info());
   8434 
   8435   // ----------------------------------------------------------------
   8436   // After this point, we've made a decision to inline this function (so
   8437   // TryInline should always return true).
   8438 
   8439   // Type-check the inlined function.
   8440   DCHECK(target_shared->has_deoptimization_support());
   8441   AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(),
   8442            target_info.scope(), target_info.osr_ast_id(), target_info.literal())
   8443       .Run();
   8444 
   8445   int inlining_id = 0;
   8446   if (top_info()->is_tracking_positions()) {
   8447     inlining_id = top_info()->TraceInlinedFunction(
   8448         target_shared, source_position(), function_state()->inlining_id());
   8449   }
   8450 
   8451   // Save the pending call context. Set up new one for the inlined function.
   8452   // The function state is new-allocated because we need to delete it
   8453   // in two different places.
   8454   FunctionState* target_state =
   8455       new FunctionState(this, &target_info, inlining_kind, inlining_id);
   8456 
   8457   HConstant* undefined = graph()->GetConstantUndefined();
   8458 
   8459   HEnvironment* inner_env =
   8460       environment()->CopyForInlining(target,
   8461                                      arguments_count,
   8462                                      function,
   8463                                      undefined,
   8464                                      function_state()->inlining_kind());
   8465 
   8466   HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
   8467   inner_env->BindContext(context);
   8468 
   8469   // Create a dematerialized arguments object for the function, also copy the
   8470   // current arguments values to use them for materialization.
   8471   HEnvironment* arguments_env = inner_env->arguments_environment();
   8472   int parameter_count = arguments_env->parameter_count();
   8473   HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
   8474   for (int i = 0; i < parameter_count; i++) {
   8475     arguments_object->AddArgument(arguments_env->Lookup(i), zone());
   8476   }
   8477 
   8478   // If the function uses arguments object then bind bind one.
   8479   if (function->scope()->arguments() != NULL) {
   8480     DCHECK(function->scope()->arguments()->IsStackAllocated());
   8481     inner_env->Bind(function->scope()->arguments(), arguments_object);
   8482   }
   8483 
   8484   // Capture the state before invoking the inlined function for deopt in the
   8485   // inlined function. This simulate has no bailout-id since it's not directly
   8486   // reachable for deopt, and is only used to capture the state. If the simulate
   8487   // becomes reachable by merging, the ast id of the simulate merged into it is
   8488   // adopted.
   8489   Add<HSimulate>(BailoutId::None());
   8490 
   8491   current_block()->UpdateEnvironment(inner_env);
   8492   Scope* saved_scope = scope();
   8493   set_scope(target_info.scope());
   8494   HEnterInlined* enter_inlined =
   8495       Add<HEnterInlined>(return_id, target, context, arguments_count, function,
   8496                          function_state()->inlining_kind(),
   8497                          function->scope()->arguments(), arguments_object);
   8498   if (top_info()->is_tracking_positions()) {
   8499     enter_inlined->set_inlining_id(inlining_id);
   8500   }
   8501   function_state()->set_entry(enter_inlined);
   8502 
   8503   VisitDeclarations(target_info.scope()->declarations());
   8504   VisitStatements(function->body());
   8505   set_scope(saved_scope);
   8506   if (HasStackOverflow()) {
   8507     // Bail out if the inline function did, as we cannot residualize a call
   8508     // instead, but do not disable optimization for the outer function.
   8509     TraceInline(target, caller, "inline graph construction failed");
   8510     target_shared->DisableOptimization(kInliningBailedOut);
   8511     current_info()->RetryOptimization(kInliningBailedOut);
   8512     delete target_state;
   8513     return true;
   8514   }
   8515 
   8516   // Update inlined nodes count.
   8517   inlined_count_ += nodes_added;
   8518 
   8519   Handle<Code> unoptimized_code(target_shared->code());
   8520   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
   8521   Handle<TypeFeedbackInfo> type_info(
   8522       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
   8523   graph()->update_type_change_checksum(type_info->own_type_change_checksum());
   8524 
   8525   TraceInline(target, caller, NULL);
   8526 
   8527   if (current_block() != NULL) {
   8528     FunctionState* state = function_state();
   8529     if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
   8530       // Falling off the end of an inlined construct call. In a test context the
   8531       // return value will always evaluate to true, in a value context the
   8532       // return value is the newly allocated receiver.
   8533       if (call_context()->IsTest()) {
   8534         Goto(inlined_test_context()->if_true(), state);
   8535       } else if (call_context()->IsEffect()) {
   8536         Goto(function_return(), state);
   8537       } else {
   8538         DCHECK(call_context()->IsValue());
   8539         AddLeaveInlined(implicit_return_value, state);
   8540       }
   8541     } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
   8542       // Falling off the end of an inlined setter call. The returned value is
   8543       // never used, the value of an assignment is always the value of the RHS
   8544       // of the assignment.
   8545       if (call_context()->IsTest()) {
   8546         inlined_test_context()->ReturnValue(implicit_return_value);
   8547       } else if (call_context()->IsEffect()) {
   8548         Goto(function_return(), state);
   8549       } else {
   8550         DCHECK(call_context()->IsValue());
   8551         AddLeaveInlined(implicit_return_value, state);
   8552       }
   8553     } else {
   8554       // Falling off the end of a normal inlined function. This basically means
   8555       // returning undefined.
   8556       if (call_context()->IsTest()) {
   8557         Goto(inlined_test_context()->if_false(), state);
   8558       } else if (call_context()->IsEffect()) {
   8559         Goto(function_return(), state);
   8560       } else {
   8561         DCHECK(call_context()->IsValue());
   8562         AddLeaveInlined(undefined, state);
   8563       }
   8564     }
   8565   }
   8566 
   8567   // Fix up the function exits.
   8568   if (inlined_test_context() != NULL) {
   8569     HBasicBlock* if_true = inlined_test_context()->if_true();
   8570     HBasicBlock* if_false = inlined_test_context()->if_false();
   8571 
   8572     HEnterInlined* entry = function_state()->entry();
   8573 
   8574     // Pop the return test context from the expression context stack.
   8575     DCHECK(ast_context() == inlined_test_context());
   8576     ClearInlinedTestContext();
   8577     delete target_state;
   8578 
   8579     // Forward to the real test context.
   8580     if (if_true->HasPredecessor()) {
   8581       entry->RegisterReturnTarget(if_true, zone());
   8582       if_true->SetJoinId(ast_id);
   8583       HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
   8584       Goto(if_true, true_target, function_state());
   8585     }
   8586     if (if_false->HasPredecessor()) {
   8587       entry->RegisterReturnTarget(if_false, zone());
   8588       if_false->SetJoinId(ast_id);
   8589       HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
   8590       Goto(if_false, false_target, function_state());
   8591     }
   8592     set_current_block(NULL);
   8593     return true;
   8594 
   8595   } else if (function_return()->HasPredecessor()) {
   8596     function_state()->entry()->RegisterReturnTarget(function_return(), zone());
   8597     function_return()->SetJoinId(ast_id);
   8598     set_current_block(function_return());
   8599   } else {
   8600     set_current_block(NULL);
   8601   }
   8602   delete target_state;
   8603   return true;
   8604 }
   8605 
   8606 
   8607 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
   8608   return TryInline(expr->target(), expr->arguments()->length(), NULL,
   8609                    expr->id(), expr->ReturnId(), NORMAL_RETURN);
   8610 }
   8611 
   8612 
   8613 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
   8614                                                 HValue* implicit_return_value) {
   8615   return TryInline(expr->target(), expr->arguments()->length(),
   8616                    implicit_return_value, expr->id(), expr->ReturnId(),
   8617                    CONSTRUCT_CALL_RETURN);
   8618 }
   8619 
   8620 
   8621 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<JSFunction> getter,
   8622                                              Handle<Map> receiver_map,
   8623                                              BailoutId ast_id,
   8624                                              BailoutId return_id) {
   8625   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
   8626   return TryInline(getter, 0, NULL, ast_id, return_id, GETTER_CALL_RETURN);
   8627 }
   8628 
   8629 
   8630 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<JSFunction> setter,
   8631                                              Handle<Map> receiver_map,
   8632                                              BailoutId id,
   8633                                              BailoutId assignment_id,
   8634                                              HValue* implicit_return_value) {
   8635   if (TryInlineApiSetter(setter, receiver_map, id)) return true;
   8636   return TryInline(setter, 1, implicit_return_value, id, assignment_id,
   8637                    SETTER_CALL_RETURN);
   8638 }
   8639 
   8640 
   8641 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
   8642                                                    Call* expr,
   8643                                                    int arguments_count) {
   8644   return TryInline(function, arguments_count, NULL, expr->id(),
   8645                    expr->ReturnId(), NORMAL_RETURN);
   8646 }
   8647 
   8648 
   8649 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
   8650   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
   8651   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
   8652   switch (id) {
   8653     case kMathExp:
   8654       if (!FLAG_fast_math) break;
   8655       // Fall through if FLAG_fast_math.
   8656     case kMathRound:
   8657     case kMathFround:
   8658     case kMathFloor:
   8659     case kMathAbs:
   8660     case kMathSqrt:
   8661     case kMathLog:
   8662     case kMathClz32:
   8663       if (expr->arguments()->length() == 1) {
   8664         HValue* argument = Pop();
   8665         Drop(2);  // Receiver and function.
   8666         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
   8667         ast_context()->ReturnInstruction(op, expr->id());
   8668         return true;
   8669       }
   8670       break;
   8671     case kMathImul:
   8672       if (expr->arguments()->length() == 2) {
   8673         HValue* right = Pop();
   8674         HValue* left = Pop();
   8675         Drop(2);  // Receiver and function.
   8676         HInstruction* op =
   8677             HMul::NewImul(isolate(), zone(), context(), left, right);
   8678         ast_context()->ReturnInstruction(op, expr->id());
   8679         return true;
   8680       }
   8681       break;
   8682     default:
   8683       // Not supported for inlining yet.
   8684       break;
   8685   }
   8686   return false;
   8687 }
   8688 
   8689 
   8690 // static
   8691 bool HOptimizedGraphBuilder::IsReadOnlyLengthDescriptor(
   8692     Handle<Map> jsarray_map) {
   8693   DCHECK(!jsarray_map->is_dictionary_map());
   8694   Isolate* isolate = jsarray_map->GetIsolate();
   8695   Handle<Name> length_string = isolate->factory()->length_string();
   8696   DescriptorArray* descriptors = jsarray_map->instance_descriptors();
   8697   int number = descriptors->SearchWithCache(*length_string, *jsarray_map);
   8698   DCHECK_NE(DescriptorArray::kNotFound, number);
   8699   return descriptors->GetDetails(number).IsReadOnly();
   8700 }
   8701 
   8702 
   8703 // static
   8704 bool HOptimizedGraphBuilder::CanInlineArrayResizeOperation(
   8705     Handle<Map> receiver_map) {
   8706   return !receiver_map.is_null() && receiver_map->prototype()->IsJSObject() &&
   8707          receiver_map->instance_type() == JS_ARRAY_TYPE &&
   8708          IsFastElementsKind(receiver_map->elements_kind()) &&
   8709          !receiver_map->is_dictionary_map() && !receiver_map->is_observed() &&
   8710          receiver_map->is_extensible() &&
   8711          (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
   8712          !IsReadOnlyLengthDescriptor(receiver_map);
   8713 }
   8714 
   8715 
   8716 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
   8717     Call* expr, Handle<JSFunction> function, Handle<Map> receiver_map,
   8718     int args_count_no_receiver) {
   8719   if (!function->shared()->HasBuiltinFunctionId()) return false;
   8720   BuiltinFunctionId id = function->shared()->builtin_function_id();
   8721   int argument_count = args_count_no_receiver + 1;  // Plus receiver.
   8722 
   8723   if (receiver_map.is_null()) {
   8724     HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
   8725     if (receiver->IsConstant() &&
   8726         HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
   8727       receiver_map =
   8728           handle(Handle<HeapObject>::cast(
   8729                      HConstant::cast(receiver)->handle(isolate()))->map());
   8730     }
   8731   }
   8732   // Try to inline calls like Math.* as operations in the calling function.
   8733   switch (id) {
   8734     case kStringCharCodeAt:
   8735     case kStringCharAt:
   8736       if (argument_count == 2) {
   8737         HValue* index = Pop();
   8738         HValue* string = Pop();
   8739         Drop(1);  // Function.
   8740         HInstruction* char_code =
   8741             BuildStringCharCodeAt(string, index);
   8742         if (id == kStringCharCodeAt) {
   8743           ast_context()->ReturnInstruction(char_code, expr->id());
   8744           return true;
   8745         }
   8746         AddInstruction(char_code);
   8747         HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
   8748         ast_context()->ReturnInstruction(result, expr->id());
   8749         return true;
   8750       }
   8751       break;
   8752     case kStringFromCharCode:
   8753       if (argument_count == 2) {
   8754         HValue* argument = Pop();
   8755         Drop(2);  // Receiver and function.
   8756         HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
   8757         ast_context()->ReturnInstruction(result, expr->id());
   8758         return true;
   8759       }
   8760       break;
   8761     case kMathExp:
   8762       if (!FLAG_fast_math) break;
   8763       // Fall through if FLAG_fast_math.
   8764     case kMathRound:
   8765     case kMathFround:
   8766     case kMathFloor:
   8767     case kMathAbs:
   8768     case kMathSqrt:
   8769     case kMathLog:
   8770     case kMathClz32:
   8771       if (argument_count == 2) {
   8772         HValue* argument = Pop();
   8773         Drop(2);  // Receiver and function.
   8774         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
   8775         ast_context()->ReturnInstruction(op, expr->id());
   8776         return true;
   8777       }
   8778       break;
   8779     case kMathPow:
   8780       if (argument_count == 3) {
   8781         HValue* right = Pop();
   8782         HValue* left = Pop();
   8783         Drop(2);  // Receiver and function.
   8784         HInstruction* result = NULL;
   8785         // Use sqrt() if exponent is 0.5 or -0.5.
   8786         if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
   8787           double exponent = HConstant::cast(right)->DoubleValue();
   8788           if (exponent == 0.5) {
   8789             result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
   8790           } else if (exponent == -0.5) {
   8791             HValue* one = graph()->GetConstant1();
   8792             HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
   8793                 left, kMathPowHalf);
   8794             // MathPowHalf doesn't have side effects so there's no need for
   8795             // an environment simulation here.
   8796             DCHECK(!sqrt->HasObservableSideEffects());
   8797             result = NewUncasted<HDiv>(one, sqrt);
   8798           } else if (exponent == 2.0) {
   8799             result = NewUncasted<HMul>(left, left);
   8800           }
   8801         }
   8802 
   8803         if (result == NULL) {
   8804           result = NewUncasted<HPower>(left, right);
   8805         }
   8806         ast_context()->ReturnInstruction(result, expr->id());
   8807         return true;
   8808       }
   8809       break;
   8810     case kMathMax:
   8811     case kMathMin:
   8812       if (argument_count == 3) {
   8813         HValue* right = Pop();
   8814         HValue* left = Pop();
   8815         Drop(2);  // Receiver and function.
   8816         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
   8817                                                      : HMathMinMax::kMathMax;
   8818         HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
   8819         ast_context()->ReturnInstruction(result, expr->id());
   8820         return true;
   8821       }
   8822       break;
   8823     case kMathImul:
   8824       if (argument_count == 3) {
   8825         HValue* right = Pop();
   8826         HValue* left = Pop();
   8827         Drop(2);  // Receiver and function.
   8828         HInstruction* result =
   8829             HMul::NewImul(isolate(), zone(), context(), left, right);
   8830         ast_context()->ReturnInstruction(result, expr->id());
   8831         return true;
   8832       }
   8833       break;
   8834     case kArrayPop: {
   8835       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
   8836       ElementsKind elements_kind = receiver_map->elements_kind();
   8837 
   8838       Drop(args_count_no_receiver);
   8839       HValue* result;
   8840       HValue* reduced_length;
   8841       HValue* receiver = Pop();
   8842 
   8843       HValue* checked_object = AddCheckMap(receiver, receiver_map);
   8844       HValue* length =
   8845           Add<HLoadNamedField>(checked_object, nullptr,
   8846                                HObjectAccess::ForArrayLength(elements_kind));
   8847 
   8848       Drop(1);  // Function.
   8849 
   8850       { NoObservableSideEffectsScope scope(this);
   8851         IfBuilder length_checker(this);
   8852 
   8853         HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
   8854             length, graph()->GetConstant0(), Token::EQ);
   8855         length_checker.Then();
   8856 
   8857         if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
   8858 
   8859         length_checker.Else();
   8860         HValue* elements = AddLoadElements(checked_object);
   8861         // Ensure that we aren't popping from a copy-on-write array.
   8862         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   8863           elements = BuildCopyElementsOnWrite(checked_object, elements,
   8864                                               elements_kind, length);
   8865         }
   8866         reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
   8867         result = AddElementAccess(elements, reduced_length, nullptr,
   8868                                   bounds_check, nullptr, elements_kind, LOAD);
   8869         HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
   8870                            ? graph()->GetConstantHole()
   8871                            : Add<HConstant>(HConstant::kHoleNaN);
   8872         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   8873           elements_kind = FAST_HOLEY_ELEMENTS;
   8874         }
   8875         AddElementAccess(elements, reduced_length, hole, bounds_check, nullptr,
   8876                          elements_kind, STORE);
   8877         Add<HStoreNamedField>(
   8878             checked_object, HObjectAccess::ForArrayLength(elements_kind),
   8879             reduced_length, STORE_TO_INITIALIZED_ENTRY);
   8880 
   8881         if (!ast_context()->IsEffect()) Push(result);
   8882 
   8883         length_checker.End();
   8884       }
   8885       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
   8886       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   8887       if (!ast_context()->IsEffect()) Drop(1);
   8888 
   8889       ast_context()->ReturnValue(result);
   8890       return true;
   8891     }
   8892     case kArrayPush: {
   8893       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
   8894       ElementsKind elements_kind = receiver_map->elements_kind();
   8895 
   8896       // If there may be elements accessors in the prototype chain, the fast
   8897       // inlined version can't be used.
   8898       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8899       // If there currently can be no elements accessors on the prototype chain,
   8900       // it doesn't mean that there won't be any later. Install a full prototype
   8901       // chain check to trap element accessors being installed on the prototype
   8902       // chain, which would cause elements to go to dictionary mode and result
   8903       // in a map change.
   8904       Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
   8905       BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
   8906 
   8907       // Protect against adding elements to the Array prototype, which needs to
   8908       // route through appropriate bottlenecks.
   8909       if (isolate()->IsFastArrayConstructorPrototypeChainIntact() &&
   8910           !prototype->IsJSArray()) {
   8911         return false;
   8912       }
   8913 
   8914       const int argc = args_count_no_receiver;
   8915       if (argc != 1) return false;
   8916 
   8917       HValue* value_to_push = Pop();
   8918       HValue* array = Pop();
   8919       Drop(1);  // Drop function.
   8920 
   8921       HInstruction* new_size = NULL;
   8922       HValue* length = NULL;
   8923 
   8924       {
   8925         NoObservableSideEffectsScope scope(this);
   8926 
   8927         length = Add<HLoadNamedField>(
   8928             array, nullptr, HObjectAccess::ForArrayLength(elements_kind));
   8929 
   8930         new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
   8931 
   8932         bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
   8933         HValue* checked_array = Add<HCheckMaps>(array, receiver_map);
   8934         BuildUncheckedMonomorphicElementAccess(
   8935             checked_array, length, value_to_push, is_array, elements_kind,
   8936             STORE, NEVER_RETURN_HOLE, STORE_AND_GROW_NO_TRANSITION);
   8937 
   8938         if (!ast_context()->IsEffect()) Push(new_size);
   8939         Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   8940         if (!ast_context()->IsEffect()) Drop(1);
   8941       }
   8942 
   8943       ast_context()->ReturnValue(new_size);
   8944       return true;
   8945     }
   8946     case kArrayShift: {
   8947       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
   8948       ElementsKind kind = receiver_map->elements_kind();
   8949 
   8950       // If there may be elements accessors in the prototype chain, the fast
   8951       // inlined version can't be used.
   8952       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8953 
   8954       // If there currently can be no elements accessors on the prototype chain,
   8955       // it doesn't mean that there won't be any later. Install a full prototype
   8956       // chain check to trap element accessors being installed on the prototype
   8957       // chain, which would cause elements to go to dictionary mode and result
   8958       // in a map change.
   8959       BuildCheckPrototypeMaps(
   8960           handle(JSObject::cast(receiver_map->prototype()), isolate()),
   8961           Handle<JSObject>::null());
   8962 
   8963       // Threshold for fast inlined Array.shift().
   8964       HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
   8965 
   8966       Drop(args_count_no_receiver);
   8967       HValue* receiver = Pop();
   8968       HValue* function = Pop();
   8969       HValue* result;
   8970 
   8971       {
   8972         NoObservableSideEffectsScope scope(this);
   8973 
   8974         HValue* length = Add<HLoadNamedField>(
   8975             receiver, nullptr, HObjectAccess::ForArrayLength(kind));
   8976 
   8977         IfBuilder if_lengthiszero(this);
   8978         HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
   8979             length, graph()->GetConstant0(), Token::EQ);
   8980         if_lengthiszero.Then();
   8981         {
   8982           if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
   8983         }
   8984         if_lengthiszero.Else();
   8985         {
   8986           HValue* elements = AddLoadElements(receiver);
   8987 
   8988           // Check if we can use the fast inlined Array.shift().
   8989           IfBuilder if_inline(this);
   8990           if_inline.If<HCompareNumericAndBranch>(
   8991               length, inline_threshold, Token::LTE);
   8992           if (IsFastSmiOrObjectElementsKind(kind)) {
   8993             // We cannot handle copy-on-write backing stores here.
   8994             if_inline.AndIf<HCompareMap>(
   8995                 elements, isolate()->factory()->fixed_array_map());
   8996           }
   8997           if_inline.Then();
   8998           {
   8999             // Remember the result.
   9000             if (!ast_context()->IsEffect()) {
   9001               Push(AddElementAccess(elements, graph()->GetConstant0(), nullptr,
   9002                                     lengthiszero, nullptr, kind, LOAD));
   9003             }
   9004 
   9005             // Compute the new length.
   9006             HValue* new_length = AddUncasted<HSub>(
   9007                 length, graph()->GetConstant1());
   9008             new_length->ClearFlag(HValue::kCanOverflow);
   9009 
   9010             // Copy the remaining elements.
   9011             LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
   9012             {
   9013               HValue* new_key = loop.BeginBody(
   9014                   graph()->GetConstant0(), new_length, Token::LT);
   9015               HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
   9016               key->ClearFlag(HValue::kCanOverflow);
   9017               ElementsKind copy_kind =
   9018                   kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
   9019               HValue* element =
   9020                   AddUncasted<HLoadKeyed>(elements, key, lengthiszero, nullptr,
   9021                                           copy_kind, ALLOW_RETURN_HOLE);
   9022               HStoreKeyed* store = Add<HStoreKeyed>(elements, new_key, element,
   9023                                                     nullptr, copy_kind);
   9024               store->SetFlag(HValue::kAllowUndefinedAsNaN);
   9025             }
   9026             loop.EndBody();
   9027 
   9028             // Put a hole at the end.
   9029             HValue* hole = IsFastSmiOrObjectElementsKind(kind)
   9030                                ? graph()->GetConstantHole()
   9031                                : Add<HConstant>(HConstant::kHoleNaN);
   9032             if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
   9033             Add<HStoreKeyed>(elements, new_length, hole, nullptr, kind,
   9034                              INITIALIZING_STORE);
   9035 
   9036             // Remember new length.
   9037             Add<HStoreNamedField>(
   9038                 receiver, HObjectAccess::ForArrayLength(kind),
   9039                 new_length, STORE_TO_INITIALIZED_ENTRY);
   9040           }
   9041           if_inline.Else();
   9042           {
   9043             Add<HPushArguments>(receiver);
   9044             result = Add<HCallJSFunction>(function, 1);
   9045             if (!ast_context()->IsEffect()) Push(result);
   9046           }
   9047           if_inline.End();
   9048         }
   9049         if_lengthiszero.End();
   9050       }
   9051       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
   9052       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   9053       if (!ast_context()->IsEffect()) Drop(1);
   9054       ast_context()->ReturnValue(result);
   9055       return true;
   9056     }
   9057     case kArrayIndexOf:
   9058     case kArrayLastIndexOf: {
   9059       if (receiver_map.is_null()) return false;
   9060       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
   9061       ElementsKind kind = receiver_map->elements_kind();
   9062       if (!IsFastElementsKind(kind)) return false;
   9063       if (receiver_map->is_observed()) return false;
   9064       if (argument_count != 2) return false;
   9065       if (!receiver_map->is_extensible()) return false;
   9066 
   9067       // If there may be elements accessors in the prototype chain, the fast
   9068       // inlined version can't be used.
   9069       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   9070 
   9071       // If there currently can be no elements accessors on the prototype chain,
   9072       // it doesn't mean that there won't be any later. Install a full prototype
   9073       // chain check to trap element accessors being installed on the prototype
   9074       // chain, which would cause elements to go to dictionary mode and result
   9075       // in a map change.
   9076       BuildCheckPrototypeMaps(
   9077           handle(JSObject::cast(receiver_map->prototype()), isolate()),
   9078           Handle<JSObject>::null());
   9079 
   9080       HValue* search_element = Pop();
   9081       HValue* receiver = Pop();
   9082       Drop(1);  // Drop function.
   9083 
   9084       ArrayIndexOfMode mode = (id == kArrayIndexOf)
   9085           ? kFirstIndexOf : kLastIndexOf;
   9086       HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
   9087 
   9088       if (!ast_context()->IsEffect()) Push(index);
   9089       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   9090       if (!ast_context()->IsEffect()) Drop(1);
   9091       ast_context()->ReturnValue(index);
   9092       return true;
   9093     }
   9094     default:
   9095       // Not yet supported for inlining.
   9096       break;
   9097   }
   9098   return false;
   9099 }
   9100 
   9101 
   9102 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
   9103                                                       HValue* receiver) {
   9104   Handle<JSFunction> function = expr->target();
   9105   int argc = expr->arguments()->length();
   9106   SmallMapList receiver_maps;
   9107   return TryInlineApiCall(function,
   9108                           receiver,
   9109                           &receiver_maps,
   9110                           argc,
   9111                           expr->id(),
   9112                           kCallApiFunction);
   9113 }
   9114 
   9115 
   9116 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
   9117     Call* expr,
   9118     HValue* receiver,
   9119     SmallMapList* receiver_maps) {
   9120   Handle<JSFunction> function = expr->target();
   9121   int argc = expr->arguments()->length();
   9122   return TryInlineApiCall(function,
   9123                           receiver,
   9124                           receiver_maps,
   9125                           argc,
   9126                           expr->id(),
   9127                           kCallApiMethod);
   9128 }
   9129 
   9130 
   9131 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<JSFunction> function,
   9132                                                 Handle<Map> receiver_map,
   9133                                                 BailoutId ast_id) {
   9134   SmallMapList receiver_maps(1, zone());
   9135   receiver_maps.Add(receiver_map, zone());
   9136   return TryInlineApiCall(function,
   9137                           NULL,  // Receiver is on expression stack.
   9138                           &receiver_maps,
   9139                           0,
   9140                           ast_id,
   9141                           kCallApiGetter);
   9142 }
   9143 
   9144 
   9145 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<JSFunction> function,
   9146                                                 Handle<Map> receiver_map,
   9147                                                 BailoutId ast_id) {
   9148   SmallMapList receiver_maps(1, zone());
   9149   receiver_maps.Add(receiver_map, zone());
   9150   return TryInlineApiCall(function,
   9151                           NULL,  // Receiver is on expression stack.
   9152                           &receiver_maps,
   9153                           1,
   9154                           ast_id,
   9155                           kCallApiSetter);
   9156 }
   9157 
   9158 
   9159 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<JSFunction> function,
   9160                                                HValue* receiver,
   9161                                                SmallMapList* receiver_maps,
   9162                                                int argc,
   9163                                                BailoutId ast_id,
   9164                                                ApiCallType call_type) {
   9165   if (function->context()->native_context() !=
   9166       top_info()->closure()->context()->native_context()) {
   9167     return false;
   9168   }
   9169   CallOptimization optimization(function);
   9170   if (!optimization.is_simple_api_call()) return false;
   9171   Handle<Map> holder_map;
   9172   for (int i = 0; i < receiver_maps->length(); ++i) {
   9173     auto map = receiver_maps->at(i);
   9174     // Don't inline calls to receivers requiring accesschecks.
   9175     if (map->is_access_check_needed()) return false;
   9176   }
   9177   if (call_type == kCallApiFunction) {
   9178     // Cannot embed a direct reference to the global proxy map
   9179     // as it maybe dropped on deserialization.
   9180     CHECK(!isolate()->serializer_enabled());
   9181     DCHECK_EQ(0, receiver_maps->length());
   9182     receiver_maps->Add(handle(function->global_proxy()->map()), zone());
   9183   }
   9184   CallOptimization::HolderLookup holder_lookup =
   9185       CallOptimization::kHolderNotFound;
   9186   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
   9187       receiver_maps->first(), &holder_lookup);
   9188   if (holder_lookup == CallOptimization::kHolderNotFound) return false;
   9189 
   9190   if (FLAG_trace_inlining) {
   9191     PrintF("Inlining api function ");
   9192     function->ShortPrint();
   9193     PrintF("\n");
   9194   }
   9195 
   9196   bool is_function = false;
   9197   bool is_store = false;
   9198   switch (call_type) {
   9199     case kCallApiFunction:
   9200     case kCallApiMethod:
   9201       // Need to check that none of the receiver maps could have changed.
   9202       Add<HCheckMaps>(receiver, receiver_maps);
   9203       // Need to ensure the chain between receiver and api_holder is intact.
   9204       if (holder_lookup == CallOptimization::kHolderFound) {
   9205         AddCheckPrototypeMaps(api_holder, receiver_maps->first());
   9206       } else {
   9207         DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
   9208       }
   9209       // Includes receiver.
   9210       PushArgumentsFromEnvironment(argc + 1);
   9211       is_function = true;
   9212       break;
   9213     case kCallApiGetter:
   9214       // Receiver and prototype chain cannot have changed.
   9215       DCHECK_EQ(0, argc);
   9216       DCHECK_NULL(receiver);
   9217       // Receiver is on expression stack.
   9218       receiver = Pop();
   9219       Add<HPushArguments>(receiver);
   9220       break;
   9221     case kCallApiSetter:
   9222       {
   9223         is_store = true;
   9224         // Receiver and prototype chain cannot have changed.
   9225         DCHECK_EQ(1, argc);
   9226         DCHECK_NULL(receiver);
   9227         // Receiver and value are on expression stack.
   9228         HValue* value = Pop();
   9229         receiver = Pop();
   9230         Add<HPushArguments>(receiver, value);
   9231         break;
   9232      }
   9233   }
   9234 
   9235   HValue* holder = NULL;
   9236   switch (holder_lookup) {
   9237     case CallOptimization::kHolderFound:
   9238       holder = Add<HConstant>(api_holder);
   9239       break;
   9240     case CallOptimization::kHolderIsReceiver:
   9241       holder = receiver;
   9242       break;
   9243     case CallOptimization::kHolderNotFound:
   9244       UNREACHABLE();
   9245       break;
   9246   }
   9247   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   9248   Handle<Object> call_data_obj(api_call_info->data(), isolate());
   9249   bool call_data_undefined = call_data_obj->IsUndefined();
   9250   HValue* call_data = Add<HConstant>(call_data_obj);
   9251   ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
   9252   ExternalReference ref = ExternalReference(&fun,
   9253                                             ExternalReference::DIRECT_API_CALL,
   9254                                             isolate());
   9255   HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
   9256 
   9257   HValue* op_vals[] = {context(), Add<HConstant>(function), call_data, holder,
   9258                        api_function_address, nullptr};
   9259 
   9260   HInstruction* call = nullptr;
   9261   if (!is_function) {
   9262     CallApiAccessorStub stub(isolate(), is_store, call_data_undefined);
   9263     Handle<Code> code = stub.GetCode();
   9264     HConstant* code_value = Add<HConstant>(code);
   9265     ApiAccessorDescriptor descriptor(isolate());
   9266     call = New<HCallWithDescriptor>(
   9267         code_value, argc + 1, descriptor,
   9268         Vector<HValue*>(op_vals, arraysize(op_vals) - 1));
   9269   } else if (argc <= CallApiFunctionWithFixedArgsStub::kMaxFixedArgs) {
   9270     CallApiFunctionWithFixedArgsStub stub(isolate(), argc, call_data_undefined);
   9271     Handle<Code> code = stub.GetCode();
   9272     HConstant* code_value = Add<HConstant>(code);
   9273     ApiFunctionWithFixedArgsDescriptor descriptor(isolate());
   9274     call = New<HCallWithDescriptor>(
   9275         code_value, argc + 1, descriptor,
   9276         Vector<HValue*>(op_vals, arraysize(op_vals) - 1));
   9277     Drop(1);  // Drop function.
   9278   } else {
   9279     op_vals[arraysize(op_vals) - 1] = Add<HConstant>(argc);
   9280     CallApiFunctionStub stub(isolate(), call_data_undefined);
   9281     Handle<Code> code = stub.GetCode();
   9282     HConstant* code_value = Add<HConstant>(code);
   9283     ApiFunctionDescriptor descriptor(isolate());
   9284     call =
   9285         New<HCallWithDescriptor>(code_value, argc + 1, descriptor,
   9286                                  Vector<HValue*>(op_vals, arraysize(op_vals)));
   9287     Drop(1);  // Drop function.
   9288   }
   9289 
   9290   ast_context()->ReturnInstruction(call, ast_id);
   9291   return true;
   9292 }
   9293 
   9294 
   9295 void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
   9296                                                 int arguments_count) {
   9297   Handle<JSFunction> known_function;
   9298   int args_count_no_receiver = arguments_count - 1;
   9299   if (function->IsConstant() &&
   9300       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9301     known_function =
   9302         Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
   9303     if (TryInlineBuiltinMethodCall(expr, known_function, Handle<Map>(),
   9304                                    args_count_no_receiver)) {
   9305       if (FLAG_trace_inlining) {
   9306         PrintF("Inlining builtin ");
   9307         known_function->ShortPrint();
   9308         PrintF("\n");
   9309       }
   9310       return;
   9311     }
   9312 
   9313     if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
   9314       return;
   9315     }
   9316   }
   9317 
   9318   PushArgumentsFromEnvironment(arguments_count);
   9319   HInvokeFunction* call =
   9320       New<HInvokeFunction>(function, known_function, arguments_count);
   9321   Drop(1);  // Function
   9322   ast_context()->ReturnInstruction(call, expr->id());
   9323 }
   9324 
   9325 
   9326 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
   9327   DCHECK(expr->expression()->IsProperty());
   9328 
   9329   if (!expr->IsMonomorphic()) {
   9330     return false;
   9331   }
   9332   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   9333   if (function_map->instance_type() != JS_FUNCTION_TYPE ||
   9334       !expr->target()->shared()->HasBuiltinFunctionId()) {
   9335     return false;
   9336   }
   9337 
   9338   switch (expr->target()->shared()->builtin_function_id()) {
   9339     case kFunctionCall: {
   9340       if (expr->arguments()->length() == 0) return false;
   9341       BuildFunctionCall(expr);
   9342       return true;
   9343     }
   9344     case kFunctionApply: {
   9345       // For .apply, only the pattern f.apply(receiver, arguments)
   9346       // is supported.
   9347       if (current_info()->scope()->arguments() == NULL) return false;
   9348 
   9349       if (!CanBeFunctionApplyArguments(expr)) return false;
   9350 
   9351       BuildFunctionApply(expr);
   9352       return true;
   9353     }
   9354     default: { return false; }
   9355   }
   9356   UNREACHABLE();
   9357 }
   9358 
   9359 
   9360 // f.apply(...)
   9361 void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
   9362   ZoneList<Expression*>* args = expr->arguments();
   9363   CHECK_ALIVE(VisitForValue(args->at(0)));
   9364   HValue* receiver = Pop();  // receiver
   9365   HValue* function = Pop();  // f
   9366   Drop(1);  // apply
   9367 
   9368   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   9369   HValue* checked_function = AddCheckMap(function, function_map);
   9370 
   9371   if (function_state()->outer() == NULL) {
   9372     HInstruction* elements = Add<HArgumentsElements>(false);
   9373     HInstruction* length = Add<HArgumentsLength>(elements);
   9374     HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
   9375     HInstruction* result = New<HApplyArguments>(function,
   9376                                                 wrapped_receiver,
   9377                                                 length,
   9378                                                 elements);
   9379     ast_context()->ReturnInstruction(result, expr->id());
   9380   } else {
   9381     // We are inside inlined function and we know exactly what is inside
   9382     // arguments object. But we need to be able to materialize at deopt.
   9383     DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
   9384               function_state()->entry()->arguments_object()->arguments_count());
   9385     HArgumentsObject* args = function_state()->entry()->arguments_object();
   9386     const ZoneList<HValue*>* arguments_values = args->arguments_values();
   9387     int arguments_count = arguments_values->length();
   9388     Push(function);
   9389     Push(BuildWrapReceiver(receiver, checked_function));
   9390     for (int i = 1; i < arguments_count; i++) {
   9391       Push(arguments_values->at(i));
   9392     }
   9393     HandleIndirectCall(expr, function, arguments_count);
   9394   }
   9395 }
   9396 
   9397 
   9398 // f.call(...)
   9399 void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
   9400   HValue* function = Top();  // f
   9401   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   9402   HValue* checked_function = AddCheckMap(function, function_map);
   9403 
   9404   // f and call are on the stack in the unoptimized code
   9405   // during evaluation of the arguments.
   9406   CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9407 
   9408   int args_length = expr->arguments()->length();
   9409   int receiver_index = args_length - 1;
   9410   // Patch the receiver.
   9411   HValue* receiver = BuildWrapReceiver(
   9412       environment()->ExpressionStackAt(receiver_index), checked_function);
   9413   environment()->SetExpressionStackAt(receiver_index, receiver);
   9414 
   9415   // Call must not be on the stack from now on.
   9416   int call_index = args_length + 1;
   9417   environment()->RemoveExpressionStackAt(call_index);
   9418 
   9419   HandleIndirectCall(expr, function, args_length);
   9420 }
   9421 
   9422 
   9423 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
   9424                                                     Handle<JSFunction> target) {
   9425   SharedFunctionInfo* shared = target->shared();
   9426   if (is_sloppy(shared->language_mode()) && !shared->native()) {
   9427     // Cannot embed a direct reference to the global proxy
   9428     // as is it dropped on deserialization.
   9429     CHECK(!isolate()->serializer_enabled());
   9430     Handle<JSObject> global_proxy(target->context()->global_proxy());
   9431     return Add<HConstant>(global_proxy);
   9432   }
   9433   return graph()->GetConstantUndefined();
   9434 }
   9435 
   9436 
   9437 void HOptimizedGraphBuilder::BuildArrayCall(Expression* expression,
   9438                                             int arguments_count,
   9439                                             HValue* function,
   9440                                             Handle<AllocationSite> site) {
   9441   Add<HCheckValue>(function, array_function());
   9442 
   9443   if (IsCallArrayInlineable(arguments_count, site)) {
   9444     BuildInlinedCallArray(expression, arguments_count, site);
   9445     return;
   9446   }
   9447 
   9448   HInstruction* call = PreProcessCall(New<HCallNewArray>(
   9449       function, arguments_count + 1, site->GetElementsKind(), site));
   9450   if (expression->IsCall()) {
   9451     Drop(1);
   9452   }
   9453   ast_context()->ReturnInstruction(call, expression->id());
   9454 }
   9455 
   9456 
   9457 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
   9458                                                   HValue* search_element,
   9459                                                   ElementsKind kind,
   9460                                                   ArrayIndexOfMode mode) {
   9461   DCHECK(IsFastElementsKind(kind));
   9462 
   9463   NoObservableSideEffectsScope no_effects(this);
   9464 
   9465   HValue* elements = AddLoadElements(receiver);
   9466   HValue* length = AddLoadArrayLength(receiver, kind);
   9467 
   9468   HValue* initial;
   9469   HValue* terminating;
   9470   Token::Value token;
   9471   LoopBuilder::Direction direction;
   9472   if (mode == kFirstIndexOf) {
   9473     initial = graph()->GetConstant0();
   9474     terminating = length;
   9475     token = Token::LT;
   9476     direction = LoopBuilder::kPostIncrement;
   9477   } else {
   9478     DCHECK_EQ(kLastIndexOf, mode);
   9479     initial = length;
   9480     terminating = graph()->GetConstant0();
   9481     token = Token::GT;
   9482     direction = LoopBuilder::kPreDecrement;
   9483   }
   9484 
   9485   Push(graph()->GetConstantMinus1());
   9486   if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
   9487     // Make sure that we can actually compare numbers correctly below, see
   9488     // https://code.google.com/p/chromium/issues/detail?id=407946 for details.
   9489     search_element = AddUncasted<HForceRepresentation>(
   9490         search_element, IsFastSmiElementsKind(kind) ? Representation::Smi()
   9491                                                     : Representation::Double());
   9492 
   9493     LoopBuilder loop(this, context(), direction);
   9494     {
   9495       HValue* index = loop.BeginBody(initial, terminating, token);
   9496       HValue* element = AddUncasted<HLoadKeyed>(
   9497           elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9498       IfBuilder if_issame(this);
   9499       if_issame.If<HCompareNumericAndBranch>(element, search_element,
   9500                                              Token::EQ_STRICT);
   9501       if_issame.Then();
   9502       {
   9503         Drop(1);
   9504         Push(index);
   9505         loop.Break();
   9506       }
   9507       if_issame.End();
   9508     }
   9509     loop.EndBody();
   9510   } else {
   9511     IfBuilder if_isstring(this);
   9512     if_isstring.If<HIsStringAndBranch>(search_element);
   9513     if_isstring.Then();
   9514     {
   9515       LoopBuilder loop(this, context(), direction);
   9516       {
   9517         HValue* index = loop.BeginBody(initial, terminating, token);
   9518         HValue* element = AddUncasted<HLoadKeyed>(
   9519             elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9520         IfBuilder if_issame(this);
   9521         if_issame.If<HIsStringAndBranch>(element);
   9522         if_issame.AndIf<HStringCompareAndBranch>(
   9523             element, search_element, Token::EQ_STRICT);
   9524         if_issame.Then();
   9525         {
   9526           Drop(1);
   9527           Push(index);
   9528           loop.Break();
   9529         }
   9530         if_issame.End();
   9531       }
   9532       loop.EndBody();
   9533     }
   9534     if_isstring.Else();
   9535     {
   9536       IfBuilder if_isnumber(this);
   9537       if_isnumber.If<HIsSmiAndBranch>(search_element);
   9538       if_isnumber.OrIf<HCompareMap>(
   9539           search_element, isolate()->factory()->heap_number_map());
   9540       if_isnumber.Then();
   9541       {
   9542         HValue* search_number =
   9543             AddUncasted<HForceRepresentation>(search_element,
   9544                                               Representation::Double());
   9545         LoopBuilder loop(this, context(), direction);
   9546         {
   9547           HValue* index = loop.BeginBody(initial, terminating, token);
   9548           HValue* element = AddUncasted<HLoadKeyed>(
   9549               elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9550 
   9551           IfBuilder if_element_isnumber(this);
   9552           if_element_isnumber.If<HIsSmiAndBranch>(element);
   9553           if_element_isnumber.OrIf<HCompareMap>(
   9554               element, isolate()->factory()->heap_number_map());
   9555           if_element_isnumber.Then();
   9556           {
   9557             HValue* number =
   9558                 AddUncasted<HForceRepresentation>(element,
   9559                                                   Representation::Double());
   9560             IfBuilder if_issame(this);
   9561             if_issame.If<HCompareNumericAndBranch>(
   9562                 number, search_number, Token::EQ_STRICT);
   9563             if_issame.Then();
   9564             {
   9565               Drop(1);
   9566               Push(index);
   9567               loop.Break();
   9568             }
   9569             if_issame.End();
   9570           }
   9571           if_element_isnumber.End();
   9572         }
   9573         loop.EndBody();
   9574       }
   9575       if_isnumber.Else();
   9576       {
   9577         LoopBuilder loop(this, context(), direction);
   9578         {
   9579           HValue* index = loop.BeginBody(initial, terminating, token);
   9580           HValue* element = AddUncasted<HLoadKeyed>(
   9581               elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9582           IfBuilder if_issame(this);
   9583           if_issame.If<HCompareObjectEqAndBranch>(
   9584               element, search_element);
   9585           if_issame.Then();
   9586           {
   9587             Drop(1);
   9588             Push(index);
   9589             loop.Break();
   9590           }
   9591           if_issame.End();
   9592         }
   9593         loop.EndBody();
   9594       }
   9595       if_isnumber.End();
   9596     }
   9597     if_isstring.End();
   9598   }
   9599 
   9600   return Pop();
   9601 }
   9602 
   9603 
   9604 bool HOptimizedGraphBuilder::TryHandleArrayCall(Call* expr, HValue* function) {
   9605   if (!array_function().is_identical_to(expr->target())) {
   9606     return false;
   9607   }
   9608 
   9609   Handle<AllocationSite> site = expr->allocation_site();
   9610   if (site.is_null()) return false;
   9611 
   9612   BuildArrayCall(expr,
   9613                  expr->arguments()->length(),
   9614                  function,
   9615                  site);
   9616   return true;
   9617 }
   9618 
   9619 
   9620 bool HOptimizedGraphBuilder::TryHandleArrayCallNew(CallNew* expr,
   9621                                                    HValue* function) {
   9622   if (!array_function().is_identical_to(expr->target())) {
   9623     return false;
   9624   }
   9625 
   9626   Handle<AllocationSite> site = expr->allocation_site();
   9627   if (site.is_null()) return false;
   9628 
   9629   BuildArrayCall(expr, expr->arguments()->length(), function, site);
   9630   return true;
   9631 }
   9632 
   9633 
   9634 bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) {
   9635   ZoneList<Expression*>* args = expr->arguments();
   9636   if (args->length() != 2) return false;
   9637   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
   9638   if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
   9639   HValue* arg_two_value = LookupAndMakeLive(arg_two->var());
   9640   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
   9641   return true;
   9642 }
   9643 
   9644 
   9645 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
   9646   DCHECK(!HasStackOverflow());
   9647   DCHECK(current_block() != NULL);
   9648   DCHECK(current_block()->HasPredecessor());
   9649   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
   9650   Expression* callee = expr->expression();
   9651   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
   9652   HInstruction* call = NULL;
   9653 
   9654   Property* prop = callee->AsProperty();
   9655   if (prop != NULL) {
   9656     CHECK_ALIVE(VisitForValue(prop->obj()));
   9657     HValue* receiver = Top();
   9658 
   9659     SmallMapList* maps;
   9660     ComputeReceiverTypes(expr, receiver, &maps, zone());
   9661 
   9662     if (prop->key()->IsPropertyName() && maps->length() > 0) {
   9663       Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
   9664       PropertyAccessInfo info(this, LOAD, maps->first(), name);
   9665       if (!info.CanAccessAsMonomorphic(maps)) {
   9666         HandlePolymorphicCallNamed(expr, receiver, maps, name);
   9667         return;
   9668       }
   9669     }
   9670     HValue* key = NULL;
   9671     if (!prop->key()->IsPropertyName()) {
   9672       CHECK_ALIVE(VisitForValue(prop->key()));
   9673       key = Pop();
   9674     }
   9675 
   9676     CHECK_ALIVE(PushLoad(prop, receiver, key));
   9677     HValue* function = Pop();
   9678 
   9679     if (function->IsConstant() &&
   9680         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9681       // Push the function under the receiver.
   9682       environment()->SetExpressionStackAt(0, function);
   9683       Push(receiver);
   9684 
   9685       Handle<JSFunction> known_function = Handle<JSFunction>::cast(
   9686           HConstant::cast(function)->handle(isolate()));
   9687       expr->set_target(known_function);
   9688 
   9689       if (TryIndirectCall(expr)) return;
   9690       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9691 
   9692       Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>();
   9693       if (TryInlineBuiltinMethodCall(expr, known_function, map,
   9694                                      expr->arguments()->length())) {
   9695         if (FLAG_trace_inlining) {
   9696           PrintF("Inlining builtin ");
   9697           known_function->ShortPrint();
   9698           PrintF("\n");
   9699         }
   9700         return;
   9701       }
   9702       if (TryInlineApiMethodCall(expr, receiver, maps)) return;
   9703 
   9704       // Wrap the receiver if necessary.
   9705       if (NeedsWrapping(maps->first(), known_function)) {
   9706         // Since HWrapReceiver currently cannot actually wrap numbers and
   9707         // strings, use the regular CallFunctionStub for method calls to wrap
   9708         // the receiver.
   9709         // TODO(verwaest): Support creation of value wrappers directly in
   9710         // HWrapReceiver.
   9711         call = New<HCallFunction>(function, argument_count,
   9712                                   ConvertReceiverMode::kNotNullOrUndefined);
   9713       } else if (TryInlineCall(expr)) {
   9714         return;
   9715       } else {
   9716         call = BuildCallConstantFunction(known_function, argument_count);
   9717       }
   9718 
   9719     } else {
   9720       ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED;
   9721       if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) {
   9722         // We have to use EAGER deoptimization here because Deoptimizer::SOFT
   9723         // gets ignored by the always-opt flag, which leads to incorrect code.
   9724         Add<HDeoptimize>(
   9725             Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments,
   9726             Deoptimizer::EAGER);
   9727         arguments_flag = ARGUMENTS_FAKED;
   9728       }
   9729 
   9730       // Push the function under the receiver.
   9731       environment()->SetExpressionStackAt(0, function);
   9732       Push(receiver);
   9733 
   9734       CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag));
   9735       call = New<HCallFunction>(function, argument_count,
   9736                                 ConvertReceiverMode::kNotNullOrUndefined);
   9737     }
   9738     PushArgumentsFromEnvironment(argument_count);
   9739 
   9740   } else {
   9741     VariableProxy* proxy = expr->expression()->AsVariableProxy();
   9742     if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) {
   9743       return Bailout(kPossibleDirectCallToEval);
   9744     }
   9745 
   9746     // The function is on the stack in the unoptimized code during
   9747     // evaluation of the arguments.
   9748     CHECK_ALIVE(VisitForValue(expr->expression()));
   9749     HValue* function = Top();
   9750     if (function->IsConstant() &&
   9751         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9752       Handle<Object> constant = HConstant::cast(function)->handle(isolate());
   9753       Handle<JSFunction> target = Handle<JSFunction>::cast(constant);
   9754       expr->SetKnownGlobalTarget(target);
   9755     }
   9756 
   9757     // Placeholder for the receiver.
   9758     Push(graph()->GetConstantUndefined());
   9759     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9760 
   9761     if (expr->IsMonomorphic() &&
   9762         !IsClassConstructor(expr->target()->shared()->kind())) {
   9763       Add<HCheckValue>(function, expr->target());
   9764 
   9765       // Patch the global object on the stack by the expected receiver.
   9766       HValue* receiver = ImplicitReceiverFor(function, expr->target());
   9767       const int receiver_index = argument_count - 1;
   9768       environment()->SetExpressionStackAt(receiver_index, receiver);
   9769 
   9770       if (TryInlineBuiltinFunctionCall(expr)) {
   9771         if (FLAG_trace_inlining) {
   9772           PrintF("Inlining builtin ");
   9773           expr->target()->ShortPrint();
   9774           PrintF("\n");
   9775         }
   9776         return;
   9777       }
   9778       if (TryInlineApiFunctionCall(expr, receiver)) return;
   9779       if (TryHandleArrayCall(expr, function)) return;
   9780       if (TryInlineCall(expr)) return;
   9781 
   9782       PushArgumentsFromEnvironment(argument_count);
   9783       call = BuildCallConstantFunction(expr->target(), argument_count);
   9784     } else {
   9785       PushArgumentsFromEnvironment(argument_count);
   9786       HCallFunction* call_function = New<HCallFunction>(
   9787           function, argument_count, ConvertReceiverMode::kNullOrUndefined);
   9788       call = call_function;
   9789       if (expr->is_uninitialized() &&
   9790           expr->IsUsingCallFeedbackICSlot(isolate())) {
   9791         // We've never seen this call before, so let's have Crankshaft learn
   9792         // through the type vector.
   9793         Handle<TypeFeedbackVector> vector =
   9794             handle(current_feedback_vector(), isolate());
   9795         FeedbackVectorSlot slot = expr->CallFeedbackICSlot();
   9796         call_function->SetVectorAndSlot(vector, slot);
   9797       }
   9798     }
   9799   }
   9800 
   9801   Drop(1);  // Drop the function.
   9802   return ast_context()->ReturnInstruction(call, expr->id());
   9803 }
   9804 
   9805 
   9806 void HOptimizedGraphBuilder::BuildInlinedCallArray(
   9807     Expression* expression,
   9808     int argument_count,
   9809     Handle<AllocationSite> site) {
   9810   DCHECK(!site.is_null());
   9811   DCHECK(argument_count >= 0 && argument_count <= 1);
   9812   NoObservableSideEffectsScope no_effects(this);
   9813 
   9814   // We should at least have the constructor on the expression stack.
   9815   HValue* constructor = environment()->ExpressionStackAt(argument_count);
   9816 
   9817   // Register on the site for deoptimization if the transition feedback changes.
   9818   top_info()->dependencies()->AssumeTransitionStable(site);
   9819   ElementsKind kind = site->GetElementsKind();
   9820   HInstruction* site_instruction = Add<HConstant>(site);
   9821 
   9822   // In the single constant argument case, we may have to adjust elements kind
   9823   // to avoid creating a packed non-empty array.
   9824   if (argument_count == 1 && !IsHoleyElementsKind(kind)) {
   9825     HValue* argument = environment()->Top();
   9826     if (argument->IsConstant()) {
   9827       HConstant* constant_argument = HConstant::cast(argument);
   9828       DCHECK(constant_argument->HasSmiValue());
   9829       int constant_array_size = constant_argument->Integer32Value();
   9830       if (constant_array_size != 0) {
   9831         kind = GetHoleyElementsKind(kind);
   9832       }
   9833     }
   9834   }
   9835 
   9836   // Build the array.
   9837   JSArrayBuilder array_builder(this,
   9838                                kind,
   9839                                site_instruction,
   9840                                constructor,
   9841                                DISABLE_ALLOCATION_SITES);
   9842   HValue* new_object = argument_count == 0
   9843       ? array_builder.AllocateEmptyArray()
   9844       : BuildAllocateArrayFromLength(&array_builder, Top());
   9845 
   9846   int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
   9847   Drop(args_to_drop);
   9848   ast_context()->ReturnValue(new_object);
   9849 }
   9850 
   9851 
   9852 // Checks whether allocation using the given constructor can be inlined.
   9853 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
   9854   return constructor->has_initial_map() &&
   9855          !IsClassConstructor(constructor->shared()->kind()) &&
   9856          constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
   9857          constructor->initial_map()->instance_size() <
   9858              HAllocate::kMaxInlineSize;
   9859 }
   9860 
   9861 
   9862 bool HOptimizedGraphBuilder::IsCallArrayInlineable(
   9863     int argument_count,
   9864     Handle<AllocationSite> site) {
   9865   Handle<JSFunction> caller = current_info()->closure();
   9866   Handle<JSFunction> target = array_function();
   9867   // We should have the function plus array arguments on the environment stack.
   9868   DCHECK(environment()->length() >= (argument_count + 1));
   9869   DCHECK(!site.is_null());
   9870 
   9871   bool inline_ok = false;
   9872   if (site->CanInlineCall()) {
   9873     // We also want to avoid inlining in certain 1 argument scenarios.
   9874     if (argument_count == 1) {
   9875       HValue* argument = Top();
   9876       if (argument->IsConstant()) {
   9877         // Do not inline if the constant length argument is not a smi or
   9878         // outside the valid range for unrolled loop initialization.
   9879         HConstant* constant_argument = HConstant::cast(argument);
   9880         if (constant_argument->HasSmiValue()) {
   9881           int value = constant_argument->Integer32Value();
   9882           inline_ok = value >= 0 && value <= kElementLoopUnrollThreshold;
   9883           if (!inline_ok) {
   9884             TraceInline(target, caller,
   9885                         "Constant length outside of valid inlining range.");
   9886           }
   9887         }
   9888       } else {
   9889         TraceInline(target, caller,
   9890                     "Dont inline [new] Array(n) where n isn't constant.");
   9891       }
   9892     } else if (argument_count == 0) {
   9893       inline_ok = true;
   9894     } else {
   9895       TraceInline(target, caller, "Too many arguments to inline.");
   9896     }
   9897   } else {
   9898     TraceInline(target, caller, "AllocationSite requested no inlining.");
   9899   }
   9900 
   9901   if (inline_ok) {
   9902     TraceInline(target, caller, NULL);
   9903   }
   9904   return inline_ok;
   9905 }
   9906 
   9907 
   9908 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
   9909   DCHECK(!HasStackOverflow());
   9910   DCHECK(current_block() != NULL);
   9911   DCHECK(current_block()->HasPredecessor());
   9912   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
   9913   int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
   9914   Factory* factory = isolate()->factory();
   9915 
   9916   // The constructor function is on the stack in the unoptimized code
   9917   // during evaluation of the arguments.
   9918   CHECK_ALIVE(VisitForValue(expr->expression()));
   9919   HValue* function = Top();
   9920   CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9921 
   9922   if (function->IsConstant() &&
   9923       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9924     Handle<Object> constant = HConstant::cast(function)->handle(isolate());
   9925     expr->SetKnownGlobalTarget(Handle<JSFunction>::cast(constant));
   9926   }
   9927 
   9928   if (FLAG_inline_construct &&
   9929       expr->IsMonomorphic() &&
   9930       IsAllocationInlineable(expr->target())) {
   9931     Handle<JSFunction> constructor = expr->target();
   9932     DCHECK(
   9933         constructor->shared()->construct_stub() ==
   9934             isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric) ||
   9935         constructor->shared()->construct_stub() ==
   9936             isolate()->builtins()->builtin(Builtins::kJSConstructStubApi));
   9937     HValue* check = Add<HCheckValue>(function, constructor);
   9938 
   9939     // Force completion of inobject slack tracking before generating
   9940     // allocation code to finalize instance size.
   9941     constructor->CompleteInobjectSlackTrackingIfActive();
   9942 
   9943     // Calculate instance size from initial map of constructor.
   9944     DCHECK(constructor->has_initial_map());
   9945     Handle<Map> initial_map(constructor->initial_map());
   9946     int instance_size = initial_map->instance_size();
   9947 
   9948     // Allocate an instance of the implicit receiver object.
   9949     HValue* size_in_bytes = Add<HConstant>(instance_size);
   9950     HAllocationMode allocation_mode;
   9951     HAllocate* receiver = BuildAllocate(
   9952         size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
   9953     receiver->set_known_initial_map(initial_map);
   9954 
   9955     // Initialize map and fields of the newly allocated object.
   9956     { NoObservableSideEffectsScope no_effects(this);
   9957       DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE);
   9958       Add<HStoreNamedField>(receiver,
   9959           HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
   9960           Add<HConstant>(initial_map));
   9961       HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
   9962       Add<HStoreNamedField>(receiver,
   9963           HObjectAccess::ForMapAndOffset(initial_map,
   9964                                          JSObject::kPropertiesOffset),
   9965           empty_fixed_array);
   9966       Add<HStoreNamedField>(receiver,
   9967           HObjectAccess::ForMapAndOffset(initial_map,
   9968                                          JSObject::kElementsOffset),
   9969           empty_fixed_array);
   9970       BuildInitializeInobjectProperties(receiver, initial_map);
   9971     }
   9972 
   9973     // Replace the constructor function with a newly allocated receiver using
   9974     // the index of the receiver from the top of the expression stack.
   9975     const int receiver_index = argument_count - 1;
   9976     DCHECK(environment()->ExpressionStackAt(receiver_index) == function);
   9977     environment()->SetExpressionStackAt(receiver_index, receiver);
   9978 
   9979     if (TryInlineConstruct(expr, receiver)) {
   9980       // Inlining worked, add a dependency on the initial map to make sure that
   9981       // this code is deoptimized whenever the initial map of the constructor
   9982       // changes.
   9983       top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
   9984       return;
   9985     }
   9986 
   9987     // TODO(mstarzinger): For now we remove the previous HAllocate and all
   9988     // corresponding instructions and instead add HPushArguments for the
   9989     // arguments in case inlining failed.  What we actually should do is for
   9990     // inlining to try to build a subgraph without mutating the parent graph.
   9991     HInstruction* instr = current_block()->last();
   9992     do {
   9993       HInstruction* prev_instr = instr->previous();
   9994       instr->DeleteAndReplaceWith(NULL);
   9995       instr = prev_instr;
   9996     } while (instr != check);
   9997     environment()->SetExpressionStackAt(receiver_index, function);
   9998   } else {
   9999     // The constructor function is both an operand to the instruction and an
   10000     // argument to the construct call.
   10001     if (TryHandleArrayCallNew(expr, function)) return;
   10002   }
   10003 
   10004   HValue* arity = Add<HConstant>(argument_count - 1);
   10005   HValue* op_vals[] = {context(), function, function, arity};
   10006   Callable callable = CodeFactory::Construct(isolate());
   10007   HConstant* stub = Add<HConstant>(callable.code());
   10008   PushArgumentsFromEnvironment(argument_count);
   10009   HInstruction* construct =
   10010       New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
   10011                                Vector<HValue*>(op_vals, arraysize(op_vals)));
   10012   return ast_context()->ReturnInstruction(construct, expr->id());
   10013 }
   10014 
   10015 
   10016 void HOptimizedGraphBuilder::BuildInitializeInobjectProperties(
   10017     HValue* receiver, Handle<Map> initial_map) {
   10018   if (initial_map->GetInObjectProperties() != 0) {
   10019     HConstant* undefined = graph()->GetConstantUndefined();
   10020     for (int i = 0; i < initial_map->GetInObjectProperties(); i++) {
   10021       int property_offset = initial_map->GetInObjectPropertyOffset(i);
   10022       Add<HStoreNamedField>(receiver, HObjectAccess::ForMapAndOffset(
   10023                                           initial_map, property_offset),
   10024                             undefined);
   10025     }
   10026   }
   10027 }
   10028 
   10029 
   10030 HValue* HGraphBuilder::BuildAllocateEmptyArrayBuffer(HValue* byte_length) {
   10031   // We HForceRepresentation here to avoid allocations during an *-to-tagged
   10032   // HChange that could cause GC while the array buffer object is not fully
   10033   // initialized.
   10034   HObjectAccess byte_length_access(HObjectAccess::ForJSArrayBufferByteLength());
   10035   byte_length = AddUncasted<HForceRepresentation>(
   10036       byte_length, byte_length_access.representation());
   10037   HAllocate* result =
   10038       BuildAllocate(Add<HConstant>(JSArrayBuffer::kSizeWithInternalFields),
   10039                     HType::JSObject(), JS_ARRAY_BUFFER_TYPE, HAllocationMode());
   10040 
   10041   HValue* native_context = BuildGetNativeContext();
   10042   Add<HStoreNamedField>(
   10043       result, HObjectAccess::ForMap(),
   10044       Add<HLoadNamedField>(
   10045           native_context, nullptr,
   10046           HObjectAccess::ForContextSlot(Context::ARRAY_BUFFER_MAP_INDEX)));
   10047 
   10048   HConstant* empty_fixed_array =
   10049       Add<HConstant>(isolate()->factory()->empty_fixed_array());
   10050   Add<HStoreNamedField>(
   10051       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
   10052       empty_fixed_array);
   10053   Add<HStoreNamedField>(
   10054       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
   10055       empty_fixed_array);
   10056   Add<HStoreNamedField>(
   10057       result, HObjectAccess::ForJSArrayBufferBackingStore().WithRepresentation(
   10058                   Representation::Smi()),
   10059       graph()->GetConstant0());
   10060   Add<HStoreNamedField>(result, byte_length_access, byte_length);
   10061   Add<HStoreNamedField>(result, HObjectAccess::ForJSArrayBufferBitFieldSlot(),
   10062                         graph()->GetConstant0());
   10063   Add<HStoreNamedField>(
   10064       result, HObjectAccess::ForJSArrayBufferBitField(),
   10065       Add<HConstant>((1 << JSArrayBuffer::IsExternal::kShift) |
   10066                      (1 << JSArrayBuffer::IsNeuterable::kShift)));
   10067 
   10068   for (int field = 0; field < v8::ArrayBuffer::kInternalFieldCount; ++field) {
   10069     Add<HStoreNamedField>(
   10070         result,
   10071         HObjectAccess::ForObservableJSObjectOffset(
   10072             JSArrayBuffer::kSize + field * kPointerSize, Representation::Smi()),
   10073         graph()->GetConstant0());
   10074   }
   10075 
   10076   return result;
   10077 }
   10078 
   10079 
   10080 template <class ViewClass>
   10081 void HGraphBuilder::BuildArrayBufferViewInitialization(
   10082     HValue* obj,
   10083     HValue* buffer,
   10084     HValue* byte_offset,
   10085     HValue* byte_length) {
   10086 
   10087   for (int offset = ViewClass::kSize;
   10088        offset < ViewClass::kSizeWithInternalFields;
   10089        offset += kPointerSize) {
   10090     Add<HStoreNamedField>(obj,
   10091         HObjectAccess::ForObservableJSObjectOffset(offset),
   10092         graph()->GetConstant0());
   10093   }
   10094 
   10095   Add<HStoreNamedField>(
   10096       obj,
   10097       HObjectAccess::ForJSArrayBufferViewByteOffset(),
   10098       byte_offset);
   10099   Add<HStoreNamedField>(
   10100       obj,
   10101       HObjectAccess::ForJSArrayBufferViewByteLength(),
   10102       byte_length);
   10103   Add<HStoreNamedField>(obj, HObjectAccess::ForJSArrayBufferViewBuffer(),
   10104                         buffer);
   10105 }
   10106 
   10107 
   10108 void HOptimizedGraphBuilder::GenerateDataViewInitialize(
   10109     CallRuntime* expr) {
   10110   ZoneList<Expression*>* arguments = expr->arguments();
   10111 
   10112   DCHECK(arguments->length()== 4);
   10113   CHECK_ALIVE(VisitForValue(arguments->at(0)));
   10114   HValue* obj = Pop();
   10115 
   10116   CHECK_ALIVE(VisitForValue(arguments->at(1)));
   10117   HValue* buffer = Pop();
   10118 
   10119   CHECK_ALIVE(VisitForValue(arguments->at(2)));
   10120   HValue* byte_offset = Pop();
   10121 
   10122   CHECK_ALIVE(VisitForValue(arguments->at(3)));
   10123   HValue* byte_length = Pop();
   10124 
   10125   {
   10126     NoObservableSideEffectsScope scope(this);
   10127     BuildArrayBufferViewInitialization<JSDataView>(
   10128         obj, buffer, byte_offset, byte_length);
   10129   }
   10130 }
   10131 
   10132 
   10133 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
   10134     ExternalArrayType array_type,
   10135     bool is_zero_byte_offset,
   10136     HValue* buffer, HValue* byte_offset, HValue* length) {
   10137   Handle<Map> external_array_map(
   10138       isolate()->heap()->MapForFixedTypedArray(array_type));
   10139 
   10140   // The HForceRepresentation is to prevent possible deopt on int-smi
   10141   // conversion after allocation but before the new object fields are set.
   10142   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   10143   HValue* elements = Add<HAllocate>(
   10144       Add<HConstant>(FixedTypedArrayBase::kHeaderSize), HType::HeapObject(),
   10145       NOT_TENURED, external_array_map->instance_type());
   10146 
   10147   AddStoreMapConstant(elements, external_array_map);
   10148   Add<HStoreNamedField>(elements,
   10149       HObjectAccess::ForFixedArrayLength(), length);
   10150 
   10151   HValue* backing_store = Add<HLoadNamedField>(
   10152       buffer, nullptr, HObjectAccess::ForJSArrayBufferBackingStore());
   10153 
   10154   HValue* typed_array_start;
   10155   if (is_zero_byte_offset) {
   10156     typed_array_start = backing_store;
   10157   } else {
   10158     HInstruction* external_pointer =
   10159         AddUncasted<HAdd>(backing_store, byte_offset);
   10160     // Arguments are checked prior to call to TypedArrayInitialize,
   10161     // including byte_offset.
   10162     external_pointer->ClearFlag(HValue::kCanOverflow);
   10163     typed_array_start = external_pointer;
   10164   }
   10165 
   10166   Add<HStoreNamedField>(elements,
   10167                         HObjectAccess::ForFixedTypedArrayBaseBasePointer(),
   10168                         graph()->GetConstant0());
   10169   Add<HStoreNamedField>(elements,
   10170                         HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
   10171                         typed_array_start);
   10172 
   10173   return elements;
   10174 }
   10175 
   10176 
   10177 HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
   10178     ExternalArrayType array_type, size_t element_size,
   10179     ElementsKind fixed_elements_kind, HValue* byte_length, HValue* length,
   10180     bool initialize) {
   10181   STATIC_ASSERT(
   10182       (FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
   10183   HValue* total_size;
   10184 
   10185   // if fixed array's elements are not aligned to object's alignment,
   10186   // we need to align the whole array to object alignment.
   10187   if (element_size % kObjectAlignment != 0) {
   10188     total_size = BuildObjectSizeAlignment(
   10189         byte_length, FixedTypedArrayBase::kHeaderSize);
   10190   } else {
   10191     total_size = AddUncasted<HAdd>(byte_length,
   10192         Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
   10193     total_size->ClearFlag(HValue::kCanOverflow);
   10194   }
   10195 
   10196   // The HForceRepresentation is to prevent possible deopt on int-smi
   10197   // conversion after allocation but before the new object fields are set.
   10198   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   10199   Handle<Map> fixed_typed_array_map(
   10200       isolate()->heap()->MapForFixedTypedArray(array_type));
   10201   HAllocate* elements =
   10202       Add<HAllocate>(total_size, HType::HeapObject(), NOT_TENURED,
   10203                      fixed_typed_array_map->instance_type());
   10204 
   10205 #ifndef V8_HOST_ARCH_64_BIT
   10206   if (array_type == kExternalFloat64Array) {
   10207     elements->MakeDoubleAligned();
   10208   }
   10209 #endif
   10210 
   10211   AddStoreMapConstant(elements, fixed_typed_array_map);
   10212 
   10213   Add<HStoreNamedField>(elements,
   10214       HObjectAccess::ForFixedArrayLength(),
   10215       length);
   10216   Add<HStoreNamedField>(
   10217       elements, HObjectAccess::ForFixedTypedArrayBaseBasePointer(), elements);
   10218 
   10219   Add<HStoreNamedField>(
   10220       elements, HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
   10221       Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()));
   10222 
   10223   HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
   10224 
   10225   if (initialize) {
   10226     LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
   10227 
   10228     HValue* backing_store = AddUncasted<HAdd>(
   10229         Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()),
   10230         elements, Strength::WEAK, AddOfExternalAndTagged);
   10231 
   10232     HValue* key = builder.BeginBody(
   10233         Add<HConstant>(static_cast<int32_t>(0)),
   10234         length, Token::LT);
   10235     Add<HStoreKeyed>(backing_store, key, filler, elements, fixed_elements_kind);
   10236 
   10237     builder.EndBody();
   10238   }
   10239   return elements;
   10240 }
   10241 
   10242 
   10243 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
   10244     CallRuntime* expr) {
   10245   ZoneList<Expression*>* arguments = expr->arguments();
   10246 
   10247   static const int kObjectArg = 0;
   10248   static const int kArrayIdArg = 1;
   10249   static const int kBufferArg = 2;
   10250   static const int kByteOffsetArg = 3;
   10251   static const int kByteLengthArg = 4;
   10252   static const int kInitializeArg = 5;
   10253   static const int kArgsLength = 6;
   10254   DCHECK(arguments->length() == kArgsLength);
   10255 
   10256 
   10257   CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
   10258   HValue* obj = Pop();
   10259 
   10260   if (!arguments->at(kArrayIdArg)->IsLiteral()) {
   10261     // This should never happen in real use, but can happen when fuzzing.
   10262     // Just bail out.
   10263     Bailout(kNeedSmiLiteral);
   10264     return;
   10265   }
   10266   Handle<Object> value =
   10267       static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
   10268   if (!value->IsSmi()) {
   10269     // This should never happen in real use, but can happen when fuzzing.
   10270     // Just bail out.
   10271     Bailout(kNeedSmiLiteral);
   10272     return;
   10273   }
   10274   int array_id = Smi::cast(*value)->value();
   10275 
   10276   HValue* buffer;
   10277   if (!arguments->at(kBufferArg)->IsNullLiteral()) {
   10278     CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
   10279     buffer = Pop();
   10280   } else {
   10281     buffer = NULL;
   10282   }
   10283 
   10284   HValue* byte_offset;
   10285   bool is_zero_byte_offset;
   10286 
   10287   if (arguments->at(kByteOffsetArg)->IsLiteral()
   10288       && Smi::FromInt(0) ==
   10289       *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
   10290     byte_offset = Add<HConstant>(static_cast<int32_t>(0));
   10291     is_zero_byte_offset = true;
   10292   } else {
   10293     CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
   10294     byte_offset = Pop();
   10295     is_zero_byte_offset = false;
   10296     DCHECK(buffer != NULL);
   10297   }
   10298 
   10299   CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
   10300   HValue* byte_length = Pop();
   10301 
   10302   CHECK(arguments->at(kInitializeArg)->IsLiteral());
   10303   bool initialize = static_cast<Literal*>(arguments->at(kInitializeArg))
   10304                         ->value()
   10305                         ->BooleanValue();
   10306 
   10307   NoObservableSideEffectsScope scope(this);
   10308   IfBuilder byte_offset_smi(this);
   10309 
   10310   if (!is_zero_byte_offset) {
   10311     byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
   10312     byte_offset_smi.Then();
   10313   }
   10314 
   10315   ExternalArrayType array_type =
   10316       kExternalInt8Array;  // Bogus initialization.
   10317   size_t element_size = 1;  // Bogus initialization.
   10318   ElementsKind fixed_elements_kind =  // Bogus initialization.
   10319       INT8_ELEMENTS;
   10320   Runtime::ArrayIdToTypeAndSize(array_id,
   10321       &array_type,
   10322       &fixed_elements_kind,
   10323       &element_size);
   10324 
   10325 
   10326   { //  byte_offset is Smi.
   10327     HValue* allocated_buffer = buffer;
   10328     if (buffer == NULL) {
   10329       allocated_buffer = BuildAllocateEmptyArrayBuffer(byte_length);
   10330     }
   10331     BuildArrayBufferViewInitialization<JSTypedArray>(obj, allocated_buffer,
   10332                                                      byte_offset, byte_length);
   10333 
   10334 
   10335     HInstruction* length = AddUncasted<HDiv>(byte_length,
   10336         Add<HConstant>(static_cast<int32_t>(element_size)));
   10337 
   10338     Add<HStoreNamedField>(obj,
   10339         HObjectAccess::ForJSTypedArrayLength(),
   10340         length);
   10341 
   10342     HValue* elements;
   10343     if (buffer != NULL) {
   10344       elements = BuildAllocateExternalElements(
   10345           array_type, is_zero_byte_offset, buffer, byte_offset, length);
   10346     } else {
   10347       DCHECK(is_zero_byte_offset);
   10348       elements = BuildAllocateFixedTypedArray(array_type, element_size,
   10349                                               fixed_elements_kind, byte_length,
   10350                                               length, initialize);
   10351     }
   10352     Add<HStoreNamedField>(
   10353         obj, HObjectAccess::ForElementsPointer(), elements);
   10354   }
   10355 
   10356   if (!is_zero_byte_offset) {
   10357     byte_offset_smi.Else();
   10358     { //  byte_offset is not Smi.
   10359       Push(obj);
   10360       CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg)));
   10361       Push(buffer);
   10362       Push(byte_offset);
   10363       Push(byte_length);
   10364       CHECK_ALIVE(VisitForValue(arguments->at(kInitializeArg)));
   10365       PushArgumentsFromEnvironment(kArgsLength);
   10366       Add<HCallRuntime>(expr->function(), kArgsLength);
   10367     }
   10368   }
   10369   byte_offset_smi.End();
   10370 }
   10371 
   10372 
   10373 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
   10374   DCHECK(expr->arguments()->length() == 0);
   10375   HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
   10376   return ast_context()->ReturnInstruction(max_smi, expr->id());
   10377 }
   10378 
   10379 
   10380 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
   10381     CallRuntime* expr) {
   10382   DCHECK(expr->arguments()->length() == 0);
   10383   HConstant* result = New<HConstant>(static_cast<int32_t>(
   10384         FLAG_typed_array_max_size_in_heap));
   10385   return ast_context()->ReturnInstruction(result, expr->id());
   10386 }
   10387 
   10388 
   10389 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
   10390     CallRuntime* expr) {
   10391   DCHECK(expr->arguments()->length() == 1);
   10392   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10393   HValue* buffer = Pop();
   10394   HInstruction* result = New<HLoadNamedField>(
   10395       buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength());
   10396   return ast_context()->ReturnInstruction(result, expr->id());
   10397 }
   10398 
   10399 
   10400 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
   10401     CallRuntime* expr) {
   10402   NoObservableSideEffectsScope scope(this);
   10403   DCHECK(expr->arguments()->length() == 1);
   10404   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10405   HValue* view = Pop();
   10406 
   10407   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
   10408       view, nullptr,
   10409       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteLengthOffset)));
   10410 }
   10411 
   10412 
   10413 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
   10414     CallRuntime* expr) {
   10415   NoObservableSideEffectsScope scope(this);
   10416   DCHECK(expr->arguments()->length() == 1);
   10417   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10418   HValue* view = Pop();
   10419 
   10420   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
   10421       view, nullptr,
   10422       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset)));
   10423 }
   10424 
   10425 
   10426 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
   10427     CallRuntime* expr) {
   10428   NoObservableSideEffectsScope scope(this);
   10429   DCHECK(expr->arguments()->length() == 1);
   10430   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10431   HValue* view = Pop();
   10432 
   10433   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
   10434       view, nullptr,
   10435       FieldIndex::ForInObjectOffset(JSTypedArray::kLengthOffset)));
   10436 }
   10437 
   10438 
   10439 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
   10440   DCHECK(!HasStackOverflow());
   10441   DCHECK(current_block() != NULL);
   10442   DCHECK(current_block()->HasPredecessor());
   10443   if (expr->is_jsruntime()) {
   10444     return Bailout(kCallToAJavaScriptRuntimeFunction);
   10445   }
   10446 
   10447   const Runtime::Function* function = expr->function();
   10448   DCHECK(function != NULL);
   10449   switch (function->function_id) {
   10450 #define CALL_INTRINSIC_GENERATOR(Name) \
   10451   case Runtime::kInline##Name:         \
   10452     return Generate##Name(expr);
   10453 
   10454     FOR_EACH_HYDROGEN_INTRINSIC(CALL_INTRINSIC_GENERATOR)
   10455 #undef CALL_INTRINSIC_GENERATOR
   10456     default: {
   10457       int argument_count = expr->arguments()->length();
   10458       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   10459       PushArgumentsFromEnvironment(argument_count);
   10460       HCallRuntime* call = New<HCallRuntime>(function, argument_count);
   10461       return ast_context()->ReturnInstruction(call, expr->id());
   10462     }
   10463   }
   10464 }
   10465 
   10466 
   10467 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
   10468   DCHECK(!HasStackOverflow());
   10469   DCHECK(current_block() != NULL);
   10470   DCHECK(current_block()->HasPredecessor());
   10471   switch (expr->op()) {
   10472     case Token::DELETE: return VisitDelete(expr);
   10473     case Token::VOID: return VisitVoid(expr);
   10474     case Token::TYPEOF: return VisitTypeof(expr);
   10475     case Token::NOT: return VisitNot(expr);
   10476     default: UNREACHABLE();
   10477   }
   10478 }
   10479 
   10480 
   10481 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
   10482   Property* prop = expr->expression()->AsProperty();
   10483   VariableProxy* proxy = expr->expression()->AsVariableProxy();
   10484   if (prop != NULL) {
   10485     CHECK_ALIVE(VisitForValue(prop->obj()));
   10486     CHECK_ALIVE(VisitForValue(prop->key()));
   10487     HValue* key = Pop();
   10488     HValue* obj = Pop();
   10489     Add<HPushArguments>(obj, key);
   10490     HInstruction* instr = New<HCallRuntime>(
   10491         Runtime::FunctionForId(is_strict(function_language_mode())
   10492                                    ? Runtime::kDeleteProperty_Strict
   10493                                    : Runtime::kDeleteProperty_Sloppy),
   10494         2);
   10495     return ast_context()->ReturnInstruction(instr, expr->id());
   10496   } else if (proxy != NULL) {
   10497     Variable* var = proxy->var();
   10498     if (var->IsUnallocatedOrGlobalSlot()) {
   10499       Bailout(kDeleteWithGlobalVariable);
   10500     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
   10501       // Result of deleting non-global variables is false.  'this' is not really
   10502       // a variable, though we implement it as one.  The subexpression does not
   10503       // have side effects.
   10504       HValue* value = var->HasThisName(isolate()) ? graph()->GetConstantTrue()
   10505                                                   : graph()->GetConstantFalse();
   10506       return ast_context()->ReturnValue(value);
   10507     } else {
   10508       Bailout(kDeleteWithNonGlobalVariable);
   10509     }
   10510   } else {
   10511     // Result of deleting non-property, non-variable reference is true.
   10512     // Evaluate the subexpression for side effects.
   10513     CHECK_ALIVE(VisitForEffect(expr->expression()));
   10514     return ast_context()->ReturnValue(graph()->GetConstantTrue());
   10515   }
   10516 }
   10517 
   10518 
   10519 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
   10520   CHECK_ALIVE(VisitForEffect(expr->expression()));
   10521   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   10522 }
   10523 
   10524 
   10525 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
   10526   CHECK_ALIVE(VisitForTypeOf(expr->expression()));
   10527   HValue* value = Pop();
   10528   HInstruction* instr = New<HTypeof>(value);
   10529   return ast_context()->ReturnInstruction(instr, expr->id());
   10530 }
   10531 
   10532 
   10533 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
   10534   if (ast_context()->IsTest()) {
   10535     TestContext* context = TestContext::cast(ast_context());
   10536     VisitForControl(expr->expression(),
   10537                     context->if_false(),
   10538                     context->if_true());
   10539     return;
   10540   }
   10541 
   10542   if (ast_context()->IsEffect()) {
   10543     VisitForEffect(expr->expression());
   10544     return;
   10545   }
   10546 
   10547   DCHECK(ast_context()->IsValue());
   10548   HBasicBlock* materialize_false = graph()->CreateBasicBlock();
   10549   HBasicBlock* materialize_true = graph()->CreateBasicBlock();
   10550   CHECK_BAILOUT(VisitForControl(expr->expression(),
   10551                                 materialize_false,
   10552                                 materialize_true));
   10553 
   10554   if (materialize_false->HasPredecessor()) {
   10555     materialize_false->SetJoinId(expr->MaterializeFalseId());
   10556     set_current_block(materialize_false);
   10557     Push(graph()->GetConstantFalse());
   10558   } else {
   10559     materialize_false = NULL;
   10560   }
   10561 
   10562   if (materialize_true->HasPredecessor()) {
   10563     materialize_true->SetJoinId(expr->MaterializeTrueId());
   10564     set_current_block(materialize_true);
   10565     Push(graph()->GetConstantTrue());
   10566   } else {
   10567     materialize_true = NULL;
   10568   }
   10569 
   10570   HBasicBlock* join =
   10571     CreateJoin(materialize_false, materialize_true, expr->id());
   10572   set_current_block(join);
   10573   if (join != NULL) return ast_context()->ReturnValue(Pop());
   10574 }
   10575 
   10576 
   10577 static Representation RepresentationFor(Type* type) {
   10578   DisallowHeapAllocation no_allocation;
   10579   if (type->Is(Type::None())) return Representation::None();
   10580   if (type->Is(Type::SignedSmall())) return Representation::Smi();
   10581   if (type->Is(Type::Signed32())) return Representation::Integer32();
   10582   if (type->Is(Type::Number())) return Representation::Double();
   10583   return Representation::Tagged();
   10584 }
   10585 
   10586 
   10587 HInstruction* HOptimizedGraphBuilder::BuildIncrement(
   10588     bool returns_original_input,
   10589     CountOperation* expr) {
   10590   // The input to the count operation is on top of the expression stack.
   10591   Representation rep = RepresentationFor(expr->type());
   10592   if (rep.IsNone() || rep.IsTagged()) {
   10593     rep = Representation::Smi();
   10594   }
   10595 
   10596   if (returns_original_input && !is_strong(function_language_mode())) {
   10597     // We need an explicit HValue representing ToNumber(input).  The
   10598     // actual HChange instruction we need is (sometimes) added in a later
   10599     // phase, so it is not available now to be used as an input to HAdd and
   10600     // as the return value.
   10601     HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
   10602     if (!rep.IsDouble()) {
   10603       number_input->SetFlag(HInstruction::kFlexibleRepresentation);
   10604       number_input->SetFlag(HInstruction::kCannotBeTagged);
   10605     }
   10606     Push(number_input);
   10607   }
   10608 
   10609   // The addition has no side effects, so we do not need
   10610   // to simulate the expression stack after this instruction.
   10611   // Any later failures deopt to the load of the input or earlier.
   10612   HConstant* delta = (expr->op() == Token::INC)
   10613       ? graph()->GetConstant1()
   10614       : graph()->GetConstantMinus1();
   10615   HInstruction* instr =
   10616       AddUncasted<HAdd>(Top(), delta, strength(function_language_mode()));
   10617   if (instr->IsAdd()) {
   10618     HAdd* add = HAdd::cast(instr);
   10619     add->set_observed_input_representation(1, rep);
   10620     add->set_observed_input_representation(2, Representation::Smi());
   10621   }
   10622   if (!is_strong(function_language_mode())) {
   10623     instr->ClearAllSideEffects();
   10624   } else {
   10625     Add<HSimulate>(expr->ToNumberId(), REMOVABLE_SIMULATE);
   10626   }
   10627   instr->SetFlag(HInstruction::kCannotBeTagged);
   10628   return instr;
   10629 }
   10630 
   10631 
   10632 void HOptimizedGraphBuilder::BuildStoreForEffect(
   10633     Expression* expr, Property* prop, FeedbackVectorSlot slot, BailoutId ast_id,
   10634     BailoutId return_id, HValue* object, HValue* key, HValue* value) {
   10635   EffectContext for_effect(this);
   10636   Push(object);
   10637   if (key != NULL) Push(key);
   10638   Push(value);
   10639   BuildStore(expr, prop, slot, ast_id, return_id);
   10640 }
   10641 
   10642 
   10643 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
   10644   DCHECK(!HasStackOverflow());
   10645   DCHECK(current_block() != NULL);
   10646   DCHECK(current_block()->HasPredecessor());
   10647   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
   10648   Expression* target = expr->expression();
   10649   VariableProxy* proxy = target->AsVariableProxy();
   10650   Property* prop = target->AsProperty();
   10651   if (proxy == NULL && prop == NULL) {
   10652     return Bailout(kInvalidLhsInCountOperation);
   10653   }
   10654 
   10655   // Match the full code generator stack by simulating an extra stack
   10656   // element for postfix operations in a non-effect context.  The return
   10657   // value is ToNumber(input).
   10658   bool returns_original_input =
   10659       expr->is_postfix() && !ast_context()->IsEffect();
   10660   HValue* input = NULL;  // ToNumber(original_input).
   10661   HValue* after = NULL;  // The result after incrementing or decrementing.
   10662 
   10663   if (proxy != NULL) {
   10664     Variable* var = proxy->var();
   10665     if (var->mode() == CONST_LEGACY)  {
   10666       return Bailout(kUnsupportedCountOperationWithConst);
   10667     }
   10668     if (var->mode() == CONST) {
   10669       return Bailout(kNonInitializerAssignmentToConst);
   10670     }
   10671     // Argument of the count operation is a variable, not a property.
   10672     DCHECK(prop == NULL);
   10673     CHECK_ALIVE(VisitForValue(target));
   10674 
   10675     after = BuildIncrement(returns_original_input, expr);
   10676     input = returns_original_input ? Top() : Pop();
   10677     Push(after);
   10678 
   10679     switch (var->location()) {
   10680       case VariableLocation::GLOBAL:
   10681       case VariableLocation::UNALLOCATED:
   10682         HandleGlobalVariableAssignment(var, after, expr->CountSlot(),
   10683                                        expr->AssignmentId());
   10684         break;
   10685 
   10686       case VariableLocation::PARAMETER:
   10687       case VariableLocation::LOCAL:
   10688         BindIfLive(var, after);
   10689         break;
   10690 
   10691       case VariableLocation::CONTEXT: {
   10692         // Bail out if we try to mutate a parameter value in a function
   10693         // using the arguments object.  We do not (yet) correctly handle the
   10694         // arguments property of the function.
   10695         if (current_info()->scope()->arguments() != NULL) {
   10696           // Parameters will rewrite to context slots.  We have no direct
   10697           // way to detect that the variable is a parameter so we use a
   10698           // linear search of the parameter list.
   10699           int count = current_info()->scope()->num_parameters();
   10700           for (int i = 0; i < count; ++i) {
   10701             if (var == current_info()->scope()->parameter(i)) {
   10702               return Bailout(kAssignmentToParameterInArgumentsObject);
   10703             }
   10704           }
   10705         }
   10706 
   10707         HValue* context = BuildContextChainWalk(var);
   10708         HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
   10709             ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
   10710         HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
   10711                                                           mode, after);
   10712         if (instr->HasObservableSideEffects()) {
   10713           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   10714         }
   10715         break;
   10716       }
   10717 
   10718       case VariableLocation::LOOKUP:
   10719         return Bailout(kLookupVariableInCountOperation);
   10720     }
   10721 
   10722     Drop(returns_original_input ? 2 : 1);
   10723     return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
   10724   }
   10725 
   10726   // Argument of the count operation is a property.
   10727   DCHECK(prop != NULL);
   10728   if (returns_original_input) Push(graph()->GetConstantUndefined());
   10729 
   10730   CHECK_ALIVE(VisitForValue(prop->obj()));
   10731   HValue* object = Top();
   10732 
   10733   HValue* key = NULL;
   10734   if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
   10735     CHECK_ALIVE(VisitForValue(prop->key()));
   10736     key = Top();
   10737   }
   10738 
   10739   CHECK_ALIVE(PushLoad(prop, object, key));
   10740 
   10741   after = BuildIncrement(returns_original_input, expr);
   10742 
   10743   if (returns_original_input) {
   10744     input = Pop();
   10745     // Drop object and key to push it again in the effect context below.
   10746     Drop(key == NULL ? 1 : 2);
   10747     environment()->SetExpressionStackAt(0, input);
   10748     CHECK_ALIVE(BuildStoreForEffect(expr, prop, expr->CountSlot(), expr->id(),
   10749                                     expr->AssignmentId(), object, key, after));
   10750     return ast_context()->ReturnValue(Pop());
   10751   }
   10752 
   10753   environment()->SetExpressionStackAt(0, after);
   10754   return BuildStore(expr, prop, expr->CountSlot(), expr->id(),
   10755                     expr->AssignmentId());
   10756 }
   10757 
   10758 
   10759 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
   10760     HValue* string,
   10761     HValue* index) {
   10762   if (string->IsConstant() && index->IsConstant()) {
   10763     HConstant* c_string = HConstant::cast(string);
   10764     HConstant* c_index = HConstant::cast(index);
   10765     if (c_string->HasStringValue() && c_index->HasNumberValue()) {
   10766       int32_t i = c_index->NumberValueAsInteger32();
   10767       Handle<String> s = c_string->StringValue();
   10768       if (i < 0 || i >= s->length()) {
   10769         return New<HConstant>(std::numeric_limits<double>::quiet_NaN());
   10770       }
   10771       return New<HConstant>(s->Get(i));
   10772     }
   10773   }
   10774   string = BuildCheckString(string);
   10775   index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
   10776   return New<HStringCharCodeAt>(string, index);
   10777 }
   10778 
   10779 
   10780 // Checks if the given shift amounts have following forms:
   10781 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
   10782 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
   10783                                              HValue* const32_minus_sa) {
   10784   if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
   10785     const HConstant* c1 = HConstant::cast(sa);
   10786     const HConstant* c2 = HConstant::cast(const32_minus_sa);
   10787     return c1->HasInteger32Value() && c2->HasInteger32Value() &&
   10788         (c1->Integer32Value() + c2->Integer32Value() == 32);
   10789   }
   10790   if (!const32_minus_sa->IsSub()) return false;
   10791   HSub* sub = HSub::cast(const32_minus_sa);
   10792   return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
   10793 }
   10794 
   10795 
   10796 // Checks if the left and the right are shift instructions with the oposite
   10797 // directions that can be replaced by one rotate right instruction or not.
   10798 // Returns the operand and the shift amount for the rotate instruction in the
   10799 // former case.
   10800 bool HGraphBuilder::MatchRotateRight(HValue* left,
   10801                                      HValue* right,
   10802                                      HValue** operand,
   10803                                      HValue** shift_amount) {
   10804   HShl* shl;
   10805   HShr* shr;
   10806   if (left->IsShl() && right->IsShr()) {
   10807     shl = HShl::cast(left);
   10808     shr = HShr::cast(right);
   10809   } else if (left->IsShr() && right->IsShl()) {
   10810     shl = HShl::cast(right);
   10811     shr = HShr::cast(left);
   10812   } else {
   10813     return false;
   10814   }
   10815   if (shl->left() != shr->left()) return false;
   10816 
   10817   if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
   10818       !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
   10819     return false;
   10820   }
   10821   *operand = shr->left();
   10822   *shift_amount = shr->right();
   10823   return true;
   10824 }
   10825 
   10826 
   10827 bool CanBeZero(HValue* right) {
   10828   if (right->IsConstant()) {
   10829     HConstant* right_const = HConstant::cast(right);
   10830     if (right_const->HasInteger32Value() &&
   10831        (right_const->Integer32Value() & 0x1f) != 0) {
   10832       return false;
   10833     }
   10834   }
   10835   return true;
   10836 }
   10837 
   10838 
   10839 HValue* HGraphBuilder::EnforceNumberType(HValue* number,
   10840                                          Type* expected) {
   10841   if (expected->Is(Type::SignedSmall())) {
   10842     return AddUncasted<HForceRepresentation>(number, Representation::Smi());
   10843   }
   10844   if (expected->Is(Type::Signed32())) {
   10845     return AddUncasted<HForceRepresentation>(number,
   10846                                              Representation::Integer32());
   10847   }
   10848   return number;
   10849 }
   10850 
   10851 
   10852 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Type** expected) {
   10853   if (value->IsConstant()) {
   10854     HConstant* constant = HConstant::cast(value);
   10855     Maybe<HConstant*> number =
   10856         constant->CopyToTruncatedNumber(isolate(), zone());
   10857     if (number.IsJust()) {
   10858       *expected = Type::Number(zone());
   10859       return AddInstruction(number.FromJust());
   10860     }
   10861   }
   10862 
   10863   // We put temporary values on the stack, which don't correspond to anything
   10864   // in baseline code. Since nothing is observable we avoid recording those
   10865   // pushes with a NoObservableSideEffectsScope.
   10866   NoObservableSideEffectsScope no_effects(this);
   10867 
   10868   Type* expected_type = *expected;
   10869 
   10870   // Separate the number type from the rest.
   10871   Type* expected_obj =
   10872       Type::Intersect(expected_type, Type::NonNumber(zone()), zone());
   10873   Type* expected_number =
   10874       Type::Intersect(expected_type, Type::Number(zone()), zone());
   10875 
   10876   // We expect to get a number.
   10877   // (We need to check first, since Type::None->Is(Type::Any()) == true.
   10878   if (expected_obj->Is(Type::None())) {
   10879     DCHECK(!expected_number->Is(Type::None(zone())));
   10880     return value;
   10881   }
   10882 
   10883   if (expected_obj->Is(Type::Undefined(zone()))) {
   10884     // This is already done by HChange.
   10885     *expected = Type::Union(expected_number, Type::Number(zone()), zone());
   10886     return value;
   10887   }
   10888 
   10889   return value;
   10890 }
   10891 
   10892 
   10893 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
   10894     BinaryOperation* expr,
   10895     HValue* left,
   10896     HValue* right,
   10897     PushBeforeSimulateBehavior push_sim_result) {
   10898   Type* left_type = expr->left()->bounds().lower;
   10899   Type* right_type = expr->right()->bounds().lower;
   10900   Type* result_type = expr->bounds().lower;
   10901   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
   10902   Handle<AllocationSite> allocation_site = expr->allocation_site();
   10903 
   10904   HAllocationMode allocation_mode;
   10905   if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
   10906     allocation_mode = HAllocationMode(allocation_site);
   10907   }
   10908   HValue* result = HGraphBuilder::BuildBinaryOperation(
   10909       expr->op(), left, right, left_type, right_type, result_type,
   10910       fixed_right_arg, allocation_mode, strength(function_language_mode()),
   10911       expr->id());
   10912   // Add a simulate after instructions with observable side effects, and
   10913   // after phis, which are the result of BuildBinaryOperation when we
   10914   // inlined some complex subgraph.
   10915   if (result->HasObservableSideEffects() || result->IsPhi()) {
   10916     if (push_sim_result == PUSH_BEFORE_SIMULATE) {
   10917       Push(result);
   10918       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   10919       Drop(1);
   10920     } else {
   10921       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   10922     }
   10923   }
   10924   return result;
   10925 }
   10926 
   10927 
   10928 HValue* HGraphBuilder::BuildBinaryOperation(
   10929     Token::Value op, HValue* left, HValue* right, Type* left_type,
   10930     Type* right_type, Type* result_type, Maybe<int> fixed_right_arg,
   10931     HAllocationMode allocation_mode, Strength strength, BailoutId opt_id) {
   10932   bool maybe_string_add = false;
   10933   if (op == Token::ADD) {
   10934     // If we are adding constant string with something for which we don't have
   10935     // a feedback yet, assume that it's also going to be a string and don't
   10936     // generate deopt instructions.
   10937     if (!left_type->IsInhabited() && right->IsConstant() &&
   10938         HConstant::cast(right)->HasStringValue()) {
   10939       left_type = Type::String();
   10940     }
   10941 
   10942     if (!right_type->IsInhabited() && left->IsConstant() &&
   10943         HConstant::cast(left)->HasStringValue()) {
   10944       right_type = Type::String();
   10945     }
   10946 
   10947     maybe_string_add = (left_type->Maybe(Type::String()) ||
   10948                         left_type->Maybe(Type::Receiver()) ||
   10949                         right_type->Maybe(Type::String()) ||
   10950                         right_type->Maybe(Type::Receiver()));
   10951   }
   10952 
   10953   Representation left_rep = RepresentationFor(left_type);
   10954   Representation right_rep = RepresentationFor(right_type);
   10955 
   10956   if (!left_type->IsInhabited()) {
   10957     Add<HDeoptimize>(
   10958         Deoptimizer::kInsufficientTypeFeedbackForLHSOfBinaryOperation,
   10959         Deoptimizer::SOFT);
   10960     left_type = Type::Any(zone());
   10961     left_rep = RepresentationFor(left_type);
   10962     maybe_string_add = op == Token::ADD;
   10963   }
   10964 
   10965   if (!right_type->IsInhabited()) {
   10966     Add<HDeoptimize>(
   10967         Deoptimizer::kInsufficientTypeFeedbackForRHSOfBinaryOperation,
   10968         Deoptimizer::SOFT);
   10969     right_type = Type::Any(zone());
   10970     right_rep = RepresentationFor(right_type);
   10971     maybe_string_add = op == Token::ADD;
   10972   }
   10973 
   10974   if (!maybe_string_add && !is_strong(strength)) {
   10975     left = TruncateToNumber(left, &left_type);
   10976     right = TruncateToNumber(right, &right_type);
   10977   }
   10978 
   10979   // Special case for string addition here.
   10980   if (op == Token::ADD &&
   10981       (left_type->Is(Type::String()) || right_type->Is(Type::String()))) {
   10982     if (is_strong(strength)) {
   10983       // In strong mode, if the one side of an addition is a string,
   10984       // the other side must be a string too.
   10985       left = BuildCheckString(left);
   10986       right = BuildCheckString(right);
   10987     } else {
   10988       // Validate type feedback for left argument.
   10989       if (left_type->Is(Type::String())) {
   10990         left = BuildCheckString(left);
   10991       }
   10992 
   10993       // Validate type feedback for right argument.
   10994       if (right_type->Is(Type::String())) {
   10995         right = BuildCheckString(right);
   10996       }
   10997 
   10998       // Convert left argument as necessary.
   10999       if (left_type->Is(Type::Number())) {
   11000         DCHECK(right_type->Is(Type::String()));
   11001         left = BuildNumberToString(left, left_type);
   11002       } else if (!left_type->Is(Type::String())) {
   11003         DCHECK(right_type->Is(Type::String()));
   11004         return AddUncasted<HStringAdd>(
   11005             left, right, allocation_mode.GetPretenureMode(),
   11006             STRING_ADD_CONVERT_LEFT, allocation_mode.feedback_site());
   11007       }
   11008 
   11009       // Convert right argument as necessary.
   11010       if (right_type->Is(Type::Number())) {
   11011         DCHECK(left_type->Is(Type::String()));
   11012         right = BuildNumberToString(right, right_type);
   11013       } else if (!right_type->Is(Type::String())) {
   11014         DCHECK(left_type->Is(Type::String()));
   11015         return AddUncasted<HStringAdd>(
   11016             left, right, allocation_mode.GetPretenureMode(),
   11017             STRING_ADD_CONVERT_RIGHT, allocation_mode.feedback_site());
   11018       }
   11019     }
   11020 
   11021     // Fast paths for empty constant strings.
   11022     Handle<String> left_string =
   11023         left->IsConstant() && HConstant::cast(left)->HasStringValue()
   11024             ? HConstant::cast(left)->StringValue()
   11025             : Handle<String>();
   11026     Handle<String> right_string =
   11027         right->IsConstant() && HConstant::cast(right)->HasStringValue()
   11028             ? HConstant::cast(right)->StringValue()
   11029             : Handle<String>();
   11030     if (!left_string.is_null() && left_string->length() == 0) return right;
   11031     if (!right_string.is_null() && right_string->length() == 0) return left;
   11032     if (!left_string.is_null() && !right_string.is_null()) {
   11033       return AddUncasted<HStringAdd>(
   11034           left, right, allocation_mode.GetPretenureMode(),
   11035           STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
   11036     }
   11037 
   11038     // Register the dependent code with the allocation site.
   11039     if (!allocation_mode.feedback_site().is_null()) {
   11040       DCHECK(!graph()->info()->IsStub());
   11041       Handle<AllocationSite> site(allocation_mode.feedback_site());
   11042       top_info()->dependencies()->AssumeTenuringDecision(site);
   11043     }
   11044 
   11045     // Inline the string addition into the stub when creating allocation
   11046     // mementos to gather allocation site feedback, or if we can statically
   11047     // infer that we're going to create a cons string.
   11048     if ((graph()->info()->IsStub() &&
   11049          allocation_mode.CreateAllocationMementos()) ||
   11050         (left->IsConstant() &&
   11051          HConstant::cast(left)->HasStringValue() &&
   11052          HConstant::cast(left)->StringValue()->length() + 1 >=
   11053            ConsString::kMinLength) ||
   11054         (right->IsConstant() &&
   11055          HConstant::cast(right)->HasStringValue() &&
   11056          HConstant::cast(right)->StringValue()->length() + 1 >=
   11057            ConsString::kMinLength)) {
   11058       return BuildStringAdd(left, right, allocation_mode);
   11059     }
   11060 
   11061     // Fallback to using the string add stub.
   11062     return AddUncasted<HStringAdd>(
   11063         left, right, allocation_mode.GetPretenureMode(), STRING_ADD_CHECK_NONE,
   11064         allocation_mode.feedback_site());
   11065   }
   11066 
   11067   if (graph()->info()->IsStub()) {
   11068     left = EnforceNumberType(left, left_type);
   11069     right = EnforceNumberType(right, right_type);
   11070   }
   11071 
   11072   Representation result_rep = RepresentationFor(result_type);
   11073 
   11074   bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
   11075                           (right_rep.IsTagged() && !right_rep.IsSmi());
   11076 
   11077   HInstruction* instr = NULL;
   11078   // Only the stub is allowed to call into the runtime, since otherwise we would
   11079   // inline several instructions (including the two pushes) for every tagged
   11080   // operation in optimized code, which is more expensive, than a stub call.
   11081   if (graph()->info()->IsStub() && is_non_primitive) {
   11082     Runtime::FunctionId function_id;
   11083     switch (op) {
   11084       default:
   11085         UNREACHABLE();
   11086       case Token::ADD:
   11087         function_id =
   11088             is_strong(strength) ? Runtime::kAdd_Strong : Runtime::kAdd;
   11089         break;
   11090       case Token::SUB:
   11091         function_id = is_strong(strength) ? Runtime::kSubtract_Strong
   11092                                           : Runtime::kSubtract;
   11093         break;
   11094       case Token::MUL:
   11095         function_id = is_strong(strength) ? Runtime::kMultiply_Strong
   11096                                           : Runtime::kMultiply;
   11097         break;
   11098       case Token::DIV:
   11099         function_id =
   11100             is_strong(strength) ? Runtime::kDivide_Strong : Runtime::kDivide;
   11101         break;
   11102       case Token::MOD:
   11103         function_id =
   11104             is_strong(strength) ? Runtime::kModulus_Strong : Runtime::kModulus;
   11105         break;
   11106       case Token::BIT_OR:
   11107         function_id = is_strong(strength) ? Runtime::kBitwiseOr_Strong
   11108                                           : Runtime::kBitwiseOr;
   11109         break;
   11110       case Token::BIT_AND:
   11111         function_id = is_strong(strength) ? Runtime::kBitwiseAnd_Strong
   11112                                           : Runtime::kBitwiseAnd;
   11113         break;
   11114       case Token::BIT_XOR:
   11115         function_id = is_strong(strength) ? Runtime::kBitwiseXor_Strong
   11116                                           : Runtime::kBitwiseXor;
   11117         break;
   11118       case Token::SAR:
   11119         function_id = is_strong(strength) ? Runtime::kShiftRight_Strong
   11120                                           : Runtime::kShiftRight;
   11121         break;
   11122       case Token::SHR:
   11123         function_id = is_strong(strength) ? Runtime::kShiftRightLogical_Strong
   11124                                           : Runtime::kShiftRightLogical;
   11125         break;
   11126       case Token::SHL:
   11127         function_id = is_strong(strength) ? Runtime::kShiftLeft_Strong
   11128                                           : Runtime::kShiftLeft;
   11129         break;
   11130     }
   11131     Add<HPushArguments>(left, right);
   11132     instr = AddUncasted<HCallRuntime>(Runtime::FunctionForId(function_id), 2);
   11133   } else {
   11134     if (is_strong(strength) && Token::IsBitOp(op)) {
   11135       // TODO(conradw): This is not efficient, but is necessary to prevent
   11136       // conversion of oddball values to numbers in strong mode. It would be
   11137       // better to prevent the conversion rather than adding a runtime check.
   11138       IfBuilder if_builder(this);
   11139       if_builder.If<HHasInstanceTypeAndBranch>(left, ODDBALL_TYPE);
   11140       if_builder.OrIf<HHasInstanceTypeAndBranch>(right, ODDBALL_TYPE);
   11141       if_builder.Then();
   11142       Add<HCallRuntime>(
   11143           Runtime::FunctionForId(Runtime::kThrowStrongModeImplicitConversion),
   11144           0);
   11145       if (!graph()->info()->IsStub()) {
   11146         Add<HSimulate>(opt_id, REMOVABLE_SIMULATE);
   11147       }
   11148       if_builder.End();
   11149     }
   11150     switch (op) {
   11151       case Token::ADD:
   11152         instr = AddUncasted<HAdd>(left, right, strength);
   11153         break;
   11154       case Token::SUB:
   11155         instr = AddUncasted<HSub>(left, right, strength);
   11156         break;
   11157       case Token::MUL:
   11158         instr = AddUncasted<HMul>(left, right, strength);
   11159         break;
   11160       case Token::MOD: {
   11161         if (fixed_right_arg.IsJust() &&
   11162             !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) {
   11163           HConstant* fixed_right =
   11164               Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust()));
   11165           IfBuilder if_same(this);
   11166           if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
   11167           if_same.Then();
   11168           if_same.ElseDeopt(Deoptimizer::kUnexpectedRHSOfBinaryOperation);
   11169           right = fixed_right;
   11170         }
   11171         instr = AddUncasted<HMod>(left, right, strength);
   11172         break;
   11173       }
   11174       case Token::DIV:
   11175         instr = AddUncasted<HDiv>(left, right, strength);
   11176         break;
   11177       case Token::BIT_XOR:
   11178       case Token::BIT_AND:
   11179         instr = AddUncasted<HBitwise>(op, left, right, strength);
   11180         break;
   11181       case Token::BIT_OR: {
   11182         HValue *operand, *shift_amount;
   11183         if (left_type->Is(Type::Signed32()) &&
   11184             right_type->Is(Type::Signed32()) &&
   11185             MatchRotateRight(left, right, &operand, &shift_amount)) {
   11186           instr = AddUncasted<HRor>(operand, shift_amount, strength);
   11187         } else {
   11188           instr = AddUncasted<HBitwise>(op, left, right, strength);
   11189         }
   11190         break;
   11191       }
   11192       case Token::SAR:
   11193         instr = AddUncasted<HSar>(left, right, strength);
   11194         break;
   11195       case Token::SHR:
   11196         instr = AddUncasted<HShr>(left, right, strength);
   11197         if (instr->IsShr() && CanBeZero(right)) {
   11198           graph()->RecordUint32Instruction(instr);
   11199         }
   11200         break;
   11201       case Token::SHL:
   11202         instr = AddUncasted<HShl>(left, right, strength);
   11203         break;
   11204       default:
   11205         UNREACHABLE();
   11206     }
   11207   }
   11208 
   11209   if (instr->IsBinaryOperation()) {
   11210     HBinaryOperation* binop = HBinaryOperation::cast(instr);
   11211     binop->set_observed_input_representation(1, left_rep);
   11212     binop->set_observed_input_representation(2, right_rep);
   11213     binop->initialize_output_representation(result_rep);
   11214     if (graph()->info()->IsStub()) {
   11215       // Stub should not call into stub.
   11216       instr->SetFlag(HValue::kCannotBeTagged);
   11217       // And should truncate on HForceRepresentation already.
   11218       if (left->IsForceRepresentation()) {
   11219         left->CopyFlag(HValue::kTruncatingToSmi, instr);
   11220         left->CopyFlag(HValue::kTruncatingToInt32, instr);
   11221       }
   11222       if (right->IsForceRepresentation()) {
   11223         right->CopyFlag(HValue::kTruncatingToSmi, instr);
   11224         right->CopyFlag(HValue::kTruncatingToInt32, instr);
   11225       }
   11226     }
   11227   }
   11228   return instr;
   11229 }
   11230 
   11231 
   11232 // Check for the form (%_ClassOf(foo) === 'BarClass').
   11233 static bool IsClassOfTest(CompareOperation* expr) {
   11234   if (expr->op() != Token::EQ_STRICT) return false;
   11235   CallRuntime* call = expr->left()->AsCallRuntime();
   11236   if (call == NULL) return false;
   11237   Literal* literal = expr->right()->AsLiteral();
   11238   if (literal == NULL) return false;
   11239   if (!literal->value()->IsString()) return false;
   11240   if (!call->is_jsruntime() &&
   11241       call->function()->function_id != Runtime::kInlineClassOf) {
   11242     return false;
   11243   }
   11244   DCHECK(call->arguments()->length() == 1);
   11245   return true;
   11246 }
   11247 
   11248 
   11249 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
   11250   DCHECK(!HasStackOverflow());
   11251   DCHECK(current_block() != NULL);
   11252   DCHECK(current_block()->HasPredecessor());
   11253   switch (expr->op()) {
   11254     case Token::COMMA:
   11255       return VisitComma(expr);
   11256     case Token::OR:
   11257     case Token::AND:
   11258       return VisitLogicalExpression(expr);
   11259     default:
   11260       return VisitArithmeticExpression(expr);
   11261   }
   11262 }
   11263 
   11264 
   11265 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) {
   11266   CHECK_ALIVE(VisitForEffect(expr->left()));
   11267   // Visit the right subexpression in the same AST context as the entire
   11268   // expression.
   11269   Visit(expr->right());
   11270 }
   11271 
   11272 
   11273 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
   11274   bool is_logical_and = expr->op() == Token::AND;
   11275   if (ast_context()->IsTest()) {
   11276     TestContext* context = TestContext::cast(ast_context());
   11277     // Translate left subexpression.
   11278     HBasicBlock* eval_right = graph()->CreateBasicBlock();
   11279     if (is_logical_and) {
   11280       CHECK_BAILOUT(VisitForControl(expr->left(),
   11281                                     eval_right,
   11282                                     context->if_false()));
   11283     } else {
   11284       CHECK_BAILOUT(VisitForControl(expr->left(),
   11285                                     context->if_true(),
   11286                                     eval_right));
   11287     }
   11288 
   11289     // Translate right subexpression by visiting it in the same AST
   11290     // context as the entire expression.
   11291     if (eval_right->HasPredecessor()) {
   11292       eval_right->SetJoinId(expr->RightId());
   11293       set_current_block(eval_right);
   11294       Visit(expr->right());
   11295     }
   11296 
   11297   } else if (ast_context()->IsValue()) {
   11298     CHECK_ALIVE(VisitForValue(expr->left()));
   11299     DCHECK(current_block() != NULL);
   11300     HValue* left_value = Top();
   11301 
   11302     // Short-circuit left values that always evaluate to the same boolean value.
   11303     if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
   11304       // l (evals true)  && r -> r
   11305       // l (evals true)  || r -> l
   11306       // l (evals false) && r -> l
   11307       // l (evals false) || r -> r
   11308       if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
   11309         Drop(1);
   11310         CHECK_ALIVE(VisitForValue(expr->right()));
   11311       }
   11312       return ast_context()->ReturnValue(Pop());
   11313     }
   11314 
   11315     // We need an extra block to maintain edge-split form.
   11316     HBasicBlock* empty_block = graph()->CreateBasicBlock();
   11317     HBasicBlock* eval_right = graph()->CreateBasicBlock();
   11318     ToBooleanStub::Types expected(expr->left()->to_boolean_types());
   11319     HBranch* test = is_logical_and
   11320         ? New<HBranch>(left_value, expected, eval_right, empty_block)
   11321         : New<HBranch>(left_value, expected, empty_block, eval_right);
   11322     FinishCurrentBlock(test);
   11323 
   11324     set_current_block(eval_right);
   11325     Drop(1);  // Value of the left subexpression.
   11326     CHECK_BAILOUT(VisitForValue(expr->right()));
   11327 
   11328     HBasicBlock* join_block =
   11329       CreateJoin(empty_block, current_block(), expr->id());
   11330     set_current_block(join_block);
   11331     return ast_context()->ReturnValue(Pop());
   11332 
   11333   } else {
   11334     DCHECK(ast_context()->IsEffect());
   11335     // In an effect context, we don't need the value of the left subexpression,
   11336     // only its control flow and side effects.  We need an extra block to
   11337     // maintain edge-split form.
   11338     HBasicBlock* empty_block = graph()->CreateBasicBlock();
   11339     HBasicBlock* right_block = graph()->CreateBasicBlock();
   11340     if (is_logical_and) {
   11341       CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
   11342     } else {
   11343       CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
   11344     }
   11345 
   11346     // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
   11347     // actually two empty blocks (one here and one inserted by
   11348     // TestContext::BuildBranch, and that they both have an HSimulate though the
   11349     // second one is not a merge node, and that we really have no good AST ID to
   11350     // put on that first HSimulate.
   11351 
   11352     if (empty_block->HasPredecessor()) {
   11353       empty_block->SetJoinId(expr->id());
   11354     } else {
   11355       empty_block = NULL;
   11356     }
   11357 
   11358     if (right_block->HasPredecessor()) {
   11359       right_block->SetJoinId(expr->RightId());
   11360       set_current_block(right_block);
   11361       CHECK_BAILOUT(VisitForEffect(expr->right()));
   11362       right_block = current_block();
   11363     } else {
   11364       right_block = NULL;
   11365     }
   11366 
   11367     HBasicBlock* join_block =
   11368       CreateJoin(empty_block, right_block, expr->id());
   11369     set_current_block(join_block);
   11370     // We did not materialize any value in the predecessor environments,
   11371     // so there is no need to handle it here.
   11372   }
   11373 }
   11374 
   11375 
   11376 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
   11377   CHECK_ALIVE(VisitForValue(expr->left()));
   11378   CHECK_ALIVE(VisitForValue(expr->right()));
   11379   SetSourcePosition(expr->position());
   11380   HValue* right = Pop();
   11381   HValue* left = Pop();
   11382   HValue* result =
   11383       BuildBinaryOperation(expr, left, right,
   11384           ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
   11385                                     : PUSH_BEFORE_SIMULATE);
   11386   if (top_info()->is_tracking_positions() && result->IsBinaryOperation()) {
   11387     HBinaryOperation::cast(result)->SetOperandPositions(
   11388         zone(),
   11389         ScriptPositionToSourcePosition(expr->left()->position()),
   11390         ScriptPositionToSourcePosition(expr->right()->position()));
   11391   }
   11392   return ast_context()->ReturnValue(result);
   11393 }
   11394 
   11395 
   11396 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
   11397                                                         Expression* sub_expr,
   11398                                                         Handle<String> check) {
   11399   CHECK_ALIVE(VisitForTypeOf(sub_expr));
   11400   SetSourcePosition(expr->position());
   11401   HValue* value = Pop();
   11402   HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
   11403   return ast_context()->ReturnControl(instr, expr->id());
   11404 }
   11405 
   11406 
   11407 static bool IsLiteralCompareBool(Isolate* isolate,
   11408                                  HValue* left,
   11409                                  Token::Value op,
   11410                                  HValue* right) {
   11411   return op == Token::EQ_STRICT &&
   11412       ((left->IsConstant() &&
   11413           HConstant::cast(left)->handle(isolate)->IsBoolean()) ||
   11414        (right->IsConstant() &&
   11415            HConstant::cast(right)->handle(isolate)->IsBoolean()));
   11416 }
   11417 
   11418 
   11419 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
   11420   DCHECK(!HasStackOverflow());
   11421   DCHECK(current_block() != NULL);
   11422   DCHECK(current_block()->HasPredecessor());
   11423 
   11424   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
   11425 
   11426   // Check for a few fast cases. The AST visiting behavior must be in sync
   11427   // with the full codegen: We don't push both left and right values onto
   11428   // the expression stack when one side is a special-case literal.
   11429   Expression* sub_expr = NULL;
   11430   Handle<String> check;
   11431   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
   11432     return HandleLiteralCompareTypeof(expr, sub_expr, check);
   11433   }
   11434   if (expr->IsLiteralCompareUndefined(&sub_expr, isolate())) {
   11435     return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
   11436   }
   11437   if (expr->IsLiteralCompareNull(&sub_expr)) {
   11438     return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
   11439   }
   11440 
   11441   if (IsClassOfTest(expr)) {
   11442     CallRuntime* call = expr->left()->AsCallRuntime();
   11443     DCHECK(call->arguments()->length() == 1);
   11444     CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11445     HValue* value = Pop();
   11446     Literal* literal = expr->right()->AsLiteral();
   11447     Handle<String> rhs = Handle<String>::cast(literal->value());
   11448     HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
   11449     return ast_context()->ReturnControl(instr, expr->id());
   11450   }
   11451 
   11452   Type* left_type = expr->left()->bounds().lower;
   11453   Type* right_type = expr->right()->bounds().lower;
   11454   Type* combined_type = expr->combined_type();
   11455 
   11456   CHECK_ALIVE(VisitForValue(expr->left()));
   11457   CHECK_ALIVE(VisitForValue(expr->right()));
   11458 
   11459   HValue* right = Pop();
   11460   HValue* left = Pop();
   11461   Token::Value op = expr->op();
   11462 
   11463   if (IsLiteralCompareBool(isolate(), left, op, right)) {
   11464     HCompareObjectEqAndBranch* result =
   11465         New<HCompareObjectEqAndBranch>(left, right);
   11466     return ast_context()->ReturnControl(result, expr->id());
   11467   }
   11468 
   11469   if (op == Token::INSTANCEOF) {
   11470     // Check to see if the rhs of the instanceof is a known function.
   11471     if (right->IsConstant() &&
   11472         HConstant::cast(right)->handle(isolate())->IsJSFunction()) {
   11473       Handle<JSFunction> constructor =
   11474           Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate()));
   11475       if (constructor->IsConstructor() &&
   11476           !constructor->map()->has_non_instance_prototype()) {
   11477         JSFunction::EnsureHasInitialMap(constructor);
   11478         DCHECK(constructor->has_initial_map());
   11479         Handle<Map> initial_map(constructor->initial_map(), isolate());
   11480         top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
   11481         HInstruction* prototype =
   11482             Add<HConstant>(handle(initial_map->prototype(), isolate()));
   11483         HHasInPrototypeChainAndBranch* result =
   11484             New<HHasInPrototypeChainAndBranch>(left, prototype);
   11485         return ast_context()->ReturnControl(result, expr->id());
   11486       }
   11487     }
   11488 
   11489     HInstanceOf* result = New<HInstanceOf>(left, right);
   11490     return ast_context()->ReturnInstruction(result, expr->id());
   11491 
   11492   } else if (op == Token::IN) {
   11493     Add<HPushArguments>(left, right);
   11494     HInstruction* result =
   11495         New<HCallRuntime>(Runtime::FunctionForId(Runtime::kHasProperty), 2);
   11496     return ast_context()->ReturnInstruction(result, expr->id());
   11497   }
   11498 
   11499   PushBeforeSimulateBehavior push_behavior =
   11500     ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
   11501                               : PUSH_BEFORE_SIMULATE;
   11502   HControlInstruction* compare = BuildCompareInstruction(
   11503       op, left, right, left_type, right_type, combined_type,
   11504       ScriptPositionToSourcePosition(expr->left()->position()),
   11505       ScriptPositionToSourcePosition(expr->right()->position()),
   11506       push_behavior, expr->id());
   11507   if (compare == NULL) return;  // Bailed out.
   11508   return ast_context()->ReturnControl(compare, expr->id());
   11509 }
   11510 
   11511 
   11512 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
   11513     Token::Value op, HValue* left, HValue* right, Type* left_type,
   11514     Type* right_type, Type* combined_type, SourcePosition left_position,
   11515     SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
   11516     BailoutId bailout_id) {
   11517   // Cases handled below depend on collected type feedback. They should
   11518   // soft deoptimize when there is no type feedback.
   11519   if (!combined_type->IsInhabited()) {
   11520     Add<HDeoptimize>(
   11521         Deoptimizer::kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,
   11522         Deoptimizer::SOFT);
   11523     combined_type = left_type = right_type = Type::Any(zone());
   11524   }
   11525 
   11526   Representation left_rep = RepresentationFor(left_type);
   11527   Representation right_rep = RepresentationFor(right_type);
   11528   Representation combined_rep = RepresentationFor(combined_type);
   11529 
   11530   if (combined_type->Is(Type::Receiver())) {
   11531     if (Token::IsEqualityOp(op)) {
   11532       // HCompareObjectEqAndBranch can only deal with object, so
   11533       // exclude numbers.
   11534       if ((left->IsConstant() &&
   11535            HConstant::cast(left)->HasNumberValue()) ||
   11536           (right->IsConstant() &&
   11537            HConstant::cast(right)->HasNumberValue())) {
   11538         Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
   11539                          Deoptimizer::SOFT);
   11540         // The caller expects a branch instruction, so make it happy.
   11541         return New<HBranch>(graph()->GetConstantTrue());
   11542       }
   11543       // Can we get away with map check and not instance type check?
   11544       HValue* operand_to_check =
   11545           left->block()->block_id() < right->block()->block_id() ? left : right;
   11546       if (combined_type->IsClass()) {
   11547         Handle<Map> map = combined_type->AsClass()->Map();
   11548         AddCheckMap(operand_to_check, map);
   11549         HCompareObjectEqAndBranch* result =
   11550             New<HCompareObjectEqAndBranch>(left, right);
   11551         if (top_info()->is_tracking_positions()) {
   11552           result->set_operand_position(zone(), 0, left_position);
   11553           result->set_operand_position(zone(), 1, right_position);
   11554         }
   11555         return result;
   11556       } else {
   11557         BuildCheckHeapObject(operand_to_check);
   11558         Add<HCheckInstanceType>(operand_to_check,
   11559                                 HCheckInstanceType::IS_JS_RECEIVER);
   11560         HCompareObjectEqAndBranch* result =
   11561             New<HCompareObjectEqAndBranch>(left, right);
   11562         return result;
   11563       }
   11564     } else {
   11565       if (combined_type->IsClass()) {
   11566         // TODO(bmeurer): This is an optimized version of an x < y, x > y,
   11567         // x <= y or x >= y, where both x and y are spec objects with the
   11568         // same map. The CompareIC collects this map for us. So if we know
   11569         // that there's no @@toPrimitive on the map (including the prototype
   11570         // chain), and both valueOf and toString are the default initial
   11571         // implementations (on the %ObjectPrototype%), then we can reduce
   11572         // the comparison to map checks on x and y, because the comparison
   11573         // will turn into a comparison of "[object CLASS]" to itself (the
   11574         // default outcome of toString, since valueOf returns a spec object).
   11575         // This is pretty much adhoc, so in TurboFan we could do a lot better
   11576         // and inline the interesting parts of ToPrimitive (actually we could
   11577         // even do that in Crankshaft but we don't want to waste too much
   11578         // time on this now).
   11579         DCHECK(Token::IsOrderedRelationalCompareOp(op));
   11580         Handle<Map> map = combined_type->AsClass()->Map();
   11581         PropertyAccessInfo value_of(this, LOAD, map,
   11582                                     isolate()->factory()->valueOf_string());
   11583         PropertyAccessInfo to_primitive(
   11584             this, LOAD, map, isolate()->factory()->to_primitive_symbol());
   11585         PropertyAccessInfo to_string(this, LOAD, map,
   11586                                      isolate()->factory()->toString_string());
   11587         PropertyAccessInfo to_string_tag(
   11588             this, LOAD, map, isolate()->factory()->to_string_tag_symbol());
   11589         if (to_primitive.CanAccessMonomorphic() && !to_primitive.IsFound() &&
   11590             to_string_tag.CanAccessMonomorphic() &&
   11591             (!to_string_tag.IsFound() || to_string_tag.IsData() ||
   11592              to_string_tag.IsDataConstant()) &&
   11593             value_of.CanAccessMonomorphic() && value_of.IsDataConstant() &&
   11594             value_of.constant().is_identical_to(isolate()->object_value_of()) &&
   11595             to_string.CanAccessMonomorphic() && to_string.IsDataConstant() &&
   11596             to_string.constant().is_identical_to(
   11597                 isolate()->object_to_string())) {
   11598           // We depend on the prototype chain to stay the same, because we
   11599           // also need to deoptimize when someone installs @@toPrimitive
   11600           // or @@toStringTag somewhere in the prototype chain.
   11601           BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
   11602                                   Handle<JSObject>::null());
   11603           AddCheckMap(left, map);
   11604           AddCheckMap(right, map);
   11605           // The caller expects a branch instruction, so make it happy.
   11606           return New<HBranch>(
   11607               graph()->GetConstantBool(op == Token::LTE || op == Token::GTE));
   11608         }
   11609       }
   11610       Bailout(kUnsupportedNonPrimitiveCompare);
   11611       return NULL;
   11612     }
   11613   } else if (combined_type->Is(Type::InternalizedString()) &&
   11614              Token::IsEqualityOp(op)) {
   11615     // If we have a constant argument, it should be consistent with the type
   11616     // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
   11617     if ((left->IsConstant() &&
   11618          !HConstant::cast(left)->HasInternalizedStringValue()) ||
   11619         (right->IsConstant() &&
   11620          !HConstant::cast(right)->HasInternalizedStringValue())) {
   11621       Add<HDeoptimize>(Deoptimizer::kTypeMismatchBetweenFeedbackAndConstant,
   11622                        Deoptimizer::SOFT);
   11623       // The caller expects a branch instruction, so make it happy.
   11624       return New<HBranch>(graph()->GetConstantTrue());
   11625     }
   11626     BuildCheckHeapObject(left);
   11627     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
   11628     BuildCheckHeapObject(right);
   11629     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
   11630     HCompareObjectEqAndBranch* result =
   11631         New<HCompareObjectEqAndBranch>(left, right);
   11632     return result;
   11633   } else if (combined_type->Is(Type::String())) {
   11634     BuildCheckHeapObject(left);
   11635     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
   11636     BuildCheckHeapObject(right);
   11637     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
   11638     HStringCompareAndBranch* result =
   11639         New<HStringCompareAndBranch>(left, right, op);
   11640     return result;
   11641   } else if (combined_type->Is(Type::Boolean())) {
   11642     AddCheckMap(left, isolate()->factory()->boolean_map());
   11643     AddCheckMap(right, isolate()->factory()->boolean_map());
   11644     if (Token::IsEqualityOp(op)) {
   11645       HCompareObjectEqAndBranch* result =
   11646           New<HCompareObjectEqAndBranch>(left, right);
   11647       return result;
   11648     }
   11649     left = Add<HLoadNamedField>(
   11650         left, nullptr,
   11651         HObjectAccess::ForOddballToNumber(Representation::Smi()));
   11652     right = Add<HLoadNamedField>(
   11653         right, nullptr,
   11654         HObjectAccess::ForOddballToNumber(Representation::Smi()));
   11655     HCompareNumericAndBranch* result =
   11656         New<HCompareNumericAndBranch>(left, right, op);
   11657     return result;
   11658   } else {
   11659     if (combined_rep.IsTagged() || combined_rep.IsNone()) {
   11660       HCompareGeneric* result = Add<HCompareGeneric>(
   11661           left, right, op, strength(function_language_mode()));
   11662       result->set_observed_input_representation(1, left_rep);
   11663       result->set_observed_input_representation(2, right_rep);
   11664       if (result->HasObservableSideEffects()) {
   11665         if (push_sim_result == PUSH_BEFORE_SIMULATE) {
   11666           Push(result);
   11667           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
   11668           Drop(1);
   11669         } else {
   11670           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
   11671         }
   11672       }
   11673       // TODO(jkummerow): Can we make this more efficient?
   11674       HBranch* branch = New<HBranch>(result);
   11675       return branch;
   11676     } else {
   11677       HCompareNumericAndBranch* result = New<HCompareNumericAndBranch>(
   11678           left, right, op, strength(function_language_mode()));
   11679       result->set_observed_input_representation(left_rep, right_rep);
   11680       if (top_info()->is_tracking_positions()) {
   11681         result->SetOperandPositions(zone(), left_position, right_position);
   11682       }
   11683       return result;
   11684     }
   11685   }
   11686 }
   11687 
   11688 
   11689 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
   11690                                                      Expression* sub_expr,
   11691                                                      NilValue nil) {
   11692   DCHECK(!HasStackOverflow());
   11693   DCHECK(current_block() != NULL);
   11694   DCHECK(current_block()->HasPredecessor());
   11695   DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
   11696   if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position());
   11697   CHECK_ALIVE(VisitForValue(sub_expr));
   11698   HValue* value = Pop();
   11699   if (expr->op() == Token::EQ_STRICT) {
   11700     HConstant* nil_constant = nil == kNullValue
   11701         ? graph()->GetConstantNull()
   11702         : graph()->GetConstantUndefined();
   11703     HCompareObjectEqAndBranch* instr =
   11704         New<HCompareObjectEqAndBranch>(value, nil_constant);
   11705     return ast_context()->ReturnControl(instr, expr->id());
   11706   } else {
   11707     DCHECK_EQ(Token::EQ, expr->op());
   11708     Type* type = expr->combined_type()->Is(Type::None())
   11709         ? Type::Any(zone()) : expr->combined_type();
   11710     HIfContinuation continuation;
   11711     BuildCompareNil(value, type, &continuation);
   11712     return ast_context()->ReturnContinuation(&continuation, expr->id());
   11713   }
   11714 }
   11715 
   11716 
   11717 void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }
   11718 
   11719 
   11720 void HOptimizedGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
   11721   UNREACHABLE();
   11722 }
   11723 
   11724 
   11725 HValue* HOptimizedGraphBuilder::AddThisFunction() {
   11726   return AddInstruction(BuildThisFunction());
   11727 }
   11728 
   11729 
   11730 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
   11731   // If we share optimized code between different closures, the
   11732   // this-function is not a constant, except inside an inlined body.
   11733   if (function_state()->outer() != NULL) {
   11734       return New<HConstant>(
   11735           function_state()->compilation_info()->closure());
   11736   } else {
   11737       return New<HThisFunction>();
   11738   }
   11739 }
   11740 
   11741 
   11742 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
   11743     Handle<JSObject> boilerplate_object,
   11744     AllocationSiteUsageContext* site_context) {
   11745   NoObservableSideEffectsScope no_effects(this);
   11746   Handle<Map> initial_map(boilerplate_object->map());
   11747   InstanceType instance_type = initial_map->instance_type();
   11748   DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
   11749 
   11750   HType type = instance_type == JS_ARRAY_TYPE
   11751       ? HType::JSArray() : HType::JSObject();
   11752   HValue* object_size_constant = Add<HConstant>(initial_map->instance_size());
   11753 
   11754   PretenureFlag pretenure_flag = NOT_TENURED;
   11755   Handle<AllocationSite> top_site(*site_context->top(), isolate());
   11756   if (FLAG_allocation_site_pretenuring) {
   11757     pretenure_flag = top_site->GetPretenureMode();
   11758   }
   11759 
   11760   Handle<AllocationSite> current_site(*site_context->current(), isolate());
   11761   if (*top_site == *current_site) {
   11762     // We install a dependency for pretenuring only on the outermost literal.
   11763     top_info()->dependencies()->AssumeTenuringDecision(top_site);
   11764   }
   11765   top_info()->dependencies()->AssumeTransitionStable(current_site);
   11766 
   11767   HInstruction* object = Add<HAllocate>(
   11768       object_size_constant, type, pretenure_flag, instance_type, top_site);
   11769 
   11770   // If allocation folding reaches Page::kMaxRegularHeapObjectSize the
   11771   // elements array may not get folded into the object. Hence, we set the
   11772   // elements pointer to empty fixed array and let store elimination remove
   11773   // this store in the folding case.
   11774   HConstant* empty_fixed_array = Add<HConstant>(
   11775       isolate()->factory()->empty_fixed_array());
   11776   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11777       empty_fixed_array);
   11778 
   11779   BuildEmitObjectHeader(boilerplate_object, object);
   11780 
   11781   // Similarly to the elements pointer, there is no guarantee that all
   11782   // property allocations can get folded, so pre-initialize all in-object
   11783   // properties to a safe value.
   11784   BuildInitializeInobjectProperties(object, initial_map);
   11785 
   11786   Handle<FixedArrayBase> elements(boilerplate_object->elements());
   11787   int elements_size = (elements->length() > 0 &&
   11788       elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
   11789           elements->Size() : 0;
   11790 
   11791   if (pretenure_flag == TENURED &&
   11792       elements->map() == isolate()->heap()->fixed_cow_array_map() &&
   11793       isolate()->heap()->InNewSpace(*elements)) {
   11794     // If we would like to pretenure a fixed cow array, we must ensure that the
   11795     // array is already in old space, otherwise we'll create too many old-to-
   11796     // new-space pointers (overflowing the store buffer).
   11797     elements = Handle<FixedArrayBase>(
   11798         isolate()->factory()->CopyAndTenureFixedCOWArray(
   11799             Handle<FixedArray>::cast(elements)));
   11800     boilerplate_object->set_elements(*elements);
   11801   }
   11802 
   11803   HInstruction* object_elements = NULL;
   11804   if (elements_size > 0) {
   11805     HValue* object_elements_size = Add<HConstant>(elements_size);
   11806     InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
   11807         ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
   11808     object_elements = Add<HAllocate>(object_elements_size, HType::HeapObject(),
   11809                                      pretenure_flag, instance_type, top_site);
   11810     BuildEmitElements(boilerplate_object, elements, object_elements,
   11811                       site_context);
   11812     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11813                           object_elements);
   11814   } else {
   11815     Handle<Object> elements_field =
   11816         Handle<Object>(boilerplate_object->elements(), isolate());
   11817     HInstruction* object_elements_cow = Add<HConstant>(elements_field);
   11818     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11819                           object_elements_cow);
   11820   }
   11821 
   11822   // Copy in-object properties.
   11823   if (initial_map->NumberOfFields() != 0 ||
   11824       initial_map->unused_property_fields() > 0) {
   11825     BuildEmitInObjectProperties(boilerplate_object, object, site_context,
   11826                                 pretenure_flag);
   11827   }
   11828   return object;
   11829 }
   11830 
   11831 
   11832 void HOptimizedGraphBuilder::BuildEmitObjectHeader(
   11833     Handle<JSObject> boilerplate_object,
   11834     HInstruction* object) {
   11835   DCHECK(boilerplate_object->properties()->length() == 0);
   11836 
   11837   Handle<Map> boilerplate_object_map(boilerplate_object->map());
   11838   AddStoreMapConstant(object, boilerplate_object_map);
   11839 
   11840   Handle<Object> properties_field =
   11841       Handle<Object>(boilerplate_object->properties(), isolate());
   11842   DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
   11843   HInstruction* properties = Add<HConstant>(properties_field);
   11844   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
   11845   Add<HStoreNamedField>(object, access, properties);
   11846 
   11847   if (boilerplate_object->IsJSArray()) {
   11848     Handle<JSArray> boilerplate_array =
   11849         Handle<JSArray>::cast(boilerplate_object);
   11850     Handle<Object> length_field =
   11851         Handle<Object>(boilerplate_array->length(), isolate());
   11852     HInstruction* length = Add<HConstant>(length_field);
   11853 
   11854     DCHECK(boilerplate_array->length()->IsSmi());
   11855     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
   11856         boilerplate_array->GetElementsKind()), length);
   11857   }
   11858 }
   11859 
   11860 
   11861 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
   11862     Handle<JSObject> boilerplate_object,
   11863     HInstruction* object,
   11864     AllocationSiteUsageContext* site_context,
   11865     PretenureFlag pretenure_flag) {
   11866   Handle<Map> boilerplate_map(boilerplate_object->map());
   11867   Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
   11868   int limit = boilerplate_map->NumberOfOwnDescriptors();
   11869 
   11870   int copied_fields = 0;
   11871   for (int i = 0; i < limit; i++) {
   11872     PropertyDetails details = descriptors->GetDetails(i);
   11873     if (details.type() != DATA) continue;
   11874     copied_fields++;
   11875     FieldIndex field_index = FieldIndex::ForDescriptor(*boilerplate_map, i);
   11876 
   11877 
   11878     int property_offset = field_index.offset();
   11879     Handle<Name> name(descriptors->GetKey(i));
   11880 
   11881     // The access for the store depends on the type of the boilerplate.
   11882     HObjectAccess access = boilerplate_object->IsJSArray() ?
   11883         HObjectAccess::ForJSArrayOffset(property_offset) :
   11884         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
   11885 
   11886     if (boilerplate_object->IsUnboxedDoubleField(field_index)) {
   11887       CHECK(!boilerplate_object->IsJSArray());
   11888       double value = boilerplate_object->RawFastDoublePropertyAt(field_index);
   11889       access = access.WithRepresentation(Representation::Double());
   11890       Add<HStoreNamedField>(object, access, Add<HConstant>(value));
   11891       continue;
   11892     }
   11893     Handle<Object> value(boilerplate_object->RawFastPropertyAt(field_index),
   11894                          isolate());
   11895 
   11896     if (value->IsJSObject()) {
   11897       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   11898       Handle<AllocationSite> current_site = site_context->EnterNewScope();
   11899       HInstruction* result =
   11900           BuildFastLiteral(value_object, site_context);
   11901       site_context->ExitScope(current_site, value_object);
   11902       Add<HStoreNamedField>(object, access, result);
   11903     } else {
   11904       Representation representation = details.representation();
   11905       HInstruction* value_instruction;
   11906 
   11907       if (representation.IsDouble()) {
   11908         // Allocate a HeapNumber box and store the value into it.
   11909         HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
   11910         HInstruction* double_box =
   11911             Add<HAllocate>(heap_number_constant, HType::HeapObject(),
   11912                 pretenure_flag, MUTABLE_HEAP_NUMBER_TYPE);
   11913         AddStoreMapConstant(double_box,
   11914             isolate()->factory()->mutable_heap_number_map());
   11915         // Unwrap the mutable heap number from the boilerplate.
   11916         HValue* double_value =
   11917             Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
   11918         Add<HStoreNamedField>(
   11919             double_box, HObjectAccess::ForHeapNumberValue(), double_value);
   11920         value_instruction = double_box;
   11921       } else if (representation.IsSmi()) {
   11922         value_instruction = value->IsUninitialized()
   11923             ? graph()->GetConstant0()
   11924             : Add<HConstant>(value);
   11925         // Ensure that value is stored as smi.
   11926         access = access.WithRepresentation(representation);
   11927       } else {
   11928         value_instruction = Add<HConstant>(value);
   11929       }
   11930 
   11931       Add<HStoreNamedField>(object, access, value_instruction);
   11932     }
   11933   }
   11934 
   11935   int inobject_properties = boilerplate_object->map()->GetInObjectProperties();
   11936   HInstruction* value_instruction =
   11937       Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
   11938   for (int i = copied_fields; i < inobject_properties; i++) {
   11939     DCHECK(boilerplate_object->IsJSObject());
   11940     int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
   11941     HObjectAccess access =
   11942         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
   11943     Add<HStoreNamedField>(object, access, value_instruction);
   11944   }
   11945 }
   11946 
   11947 
   11948 void HOptimizedGraphBuilder::BuildEmitElements(
   11949     Handle<JSObject> boilerplate_object,
   11950     Handle<FixedArrayBase> elements,
   11951     HValue* object_elements,
   11952     AllocationSiteUsageContext* site_context) {
   11953   ElementsKind kind = boilerplate_object->map()->elements_kind();
   11954   int elements_length = elements->length();
   11955   HValue* object_elements_length = Add<HConstant>(elements_length);
   11956   BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
   11957 
   11958   // Copy elements backing store content.
   11959   if (elements->IsFixedDoubleArray()) {
   11960     BuildEmitFixedDoubleArray(elements, kind, object_elements);
   11961   } else if (elements->IsFixedArray()) {
   11962     BuildEmitFixedArray(elements, kind, object_elements,
   11963                         site_context);
   11964   } else {
   11965     UNREACHABLE();
   11966   }
   11967 }
   11968 
   11969 
   11970 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
   11971     Handle<FixedArrayBase> elements,
   11972     ElementsKind kind,
   11973     HValue* object_elements) {
   11974   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   11975   int elements_length = elements->length();
   11976   for (int i = 0; i < elements_length; i++) {
   11977     HValue* key_constant = Add<HConstant>(i);
   11978     HInstruction* value_instruction =
   11979         Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
   11980                         kind, ALLOW_RETURN_HOLE);
   11981     HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
   11982                                            value_instruction, nullptr, kind);
   11983     store->SetFlag(HValue::kAllowUndefinedAsNaN);
   11984   }
   11985 }
   11986 
   11987 
   11988 void HOptimizedGraphBuilder::BuildEmitFixedArray(
   11989     Handle<FixedArrayBase> elements,
   11990     ElementsKind kind,
   11991     HValue* object_elements,
   11992     AllocationSiteUsageContext* site_context) {
   11993   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   11994   int elements_length = elements->length();
   11995   Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
   11996   for (int i = 0; i < elements_length; i++) {
   11997     Handle<Object> value(fast_elements->get(i), isolate());
   11998     HValue* key_constant = Add<HConstant>(i);
   11999     if (value->IsJSObject()) {
   12000       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   12001       Handle<AllocationSite> current_site = site_context->EnterNewScope();
   12002       HInstruction* result =
   12003           BuildFastLiteral(value_object, site_context);
   12004       site_context->ExitScope(current_site, value_object);
   12005       Add<HStoreKeyed>(object_elements, key_constant, result, nullptr, kind);
   12006     } else {
   12007       ElementsKind copy_kind =
   12008           kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
   12009       HInstruction* value_instruction =
   12010           Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
   12011                           copy_kind, ALLOW_RETURN_HOLE);
   12012       Add<HStoreKeyed>(object_elements, key_constant, value_instruction,
   12013                        nullptr, copy_kind);
   12014     }
   12015   }
   12016 }
   12017 
   12018 
   12019 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
   12020   DCHECK(!HasStackOverflow());
   12021   DCHECK(current_block() != NULL);
   12022   DCHECK(current_block()->HasPredecessor());
   12023   HInstruction* instr = BuildThisFunction();
   12024   return ast_context()->ReturnInstruction(instr, expr->id());
   12025 }
   12026 
   12027 
   12028 void HOptimizedGraphBuilder::VisitSuperPropertyReference(
   12029     SuperPropertyReference* expr) {
   12030   DCHECK(!HasStackOverflow());
   12031   DCHECK(current_block() != NULL);
   12032   DCHECK(current_block()->HasPredecessor());
   12033   return Bailout(kSuperReference);
   12034 }
   12035 
   12036 
   12037 void HOptimizedGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
   12038   DCHECK(!HasStackOverflow());
   12039   DCHECK(current_block() != NULL);
   12040   DCHECK(current_block()->HasPredecessor());
   12041   return Bailout(kSuperReference);
   12042 }
   12043 
   12044 
   12045 void HOptimizedGraphBuilder::VisitDeclarations(
   12046     ZoneList<Declaration*>* declarations) {
   12047   DCHECK(globals_.is_empty());
   12048   AstVisitor::VisitDeclarations(declarations);
   12049   if (!globals_.is_empty()) {
   12050     Handle<FixedArray> array =
   12051        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
   12052     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
   12053     int flags =
   12054         DeclareGlobalsEvalFlag::encode(current_info()->is_eval()) |
   12055         DeclareGlobalsNativeFlag::encode(current_info()->is_native()) |
   12056         DeclareGlobalsLanguageMode::encode(current_info()->language_mode());
   12057     Add<HDeclareGlobals>(array, flags);
   12058     globals_.Rewind(0);
   12059   }
   12060 }
   12061 
   12062 
   12063 void HOptimizedGraphBuilder::VisitVariableDeclaration(
   12064     VariableDeclaration* declaration) {
   12065   VariableProxy* proxy = declaration->proxy();
   12066   VariableMode mode = declaration->mode();
   12067   Variable* variable = proxy->var();
   12068   bool hole_init = mode == LET || mode == CONST || mode == CONST_LEGACY;
   12069   switch (variable->location()) {
   12070     case VariableLocation::GLOBAL:
   12071     case VariableLocation::UNALLOCATED:
   12072       globals_.Add(variable->name(), zone());
   12073       globals_.Add(variable->binding_needs_init()
   12074                        ? isolate()->factory()->the_hole_value()
   12075                        : isolate()->factory()->undefined_value(), zone());
   12076       return;
   12077     case VariableLocation::PARAMETER:
   12078     case VariableLocation::LOCAL:
   12079       if (hole_init) {
   12080         HValue* value = graph()->GetConstantHole();
   12081         environment()->Bind(variable, value);
   12082       }
   12083       break;
   12084     case VariableLocation::CONTEXT:
   12085       if (hole_init) {
   12086         HValue* value = graph()->GetConstantHole();
   12087         HValue* context = environment()->context();
   12088         HStoreContextSlot* store = Add<HStoreContextSlot>(
   12089             context, variable->index(), HStoreContextSlot::kNoCheck, value);
   12090         if (store->HasObservableSideEffects()) {
   12091           Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
   12092         }
   12093       }
   12094       break;
   12095     case VariableLocation::LOOKUP:
   12096       return Bailout(kUnsupportedLookupSlotInDeclaration);
   12097   }
   12098 }
   12099 
   12100 
   12101 void HOptimizedGraphBuilder::VisitFunctionDeclaration(
   12102     FunctionDeclaration* declaration) {
   12103   VariableProxy* proxy = declaration->proxy();
   12104   Variable* variable = proxy->var();
   12105   switch (variable->location()) {
   12106     case VariableLocation::GLOBAL:
   12107     case VariableLocation::UNALLOCATED: {
   12108       globals_.Add(variable->name(), zone());
   12109       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
   12110           declaration->fun(), current_info()->script(), top_info());
   12111       // Check for stack-overflow exception.
   12112       if (function.is_null()) return SetStackOverflow();
   12113       globals_.Add(function, zone());
   12114       return;
   12115     }
   12116     case VariableLocation::PARAMETER:
   12117     case VariableLocation::LOCAL: {
   12118       CHECK_ALIVE(VisitForValue(declaration->fun()));
   12119       HValue* value = Pop();
   12120       BindIfLive(variable, value);
   12121       break;
   12122     }
   12123     case VariableLocation::CONTEXT: {
   12124       CHECK_ALIVE(VisitForValue(declaration->fun()));
   12125       HValue* value = Pop();
   12126       HValue* context = environment()->context();
   12127       HStoreContextSlot* store = Add<HStoreContextSlot>(
   12128           context, variable->index(), HStoreContextSlot::kNoCheck, value);
   12129       if (store->HasObservableSideEffects()) {
   12130         Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
   12131       }
   12132       break;
   12133     }
   12134     case VariableLocation::LOOKUP:
   12135       return Bailout(kUnsupportedLookupSlotInDeclaration);
   12136   }
   12137 }
   12138 
   12139 
   12140 void HOptimizedGraphBuilder::VisitImportDeclaration(
   12141     ImportDeclaration* declaration) {
   12142   UNREACHABLE();
   12143 }
   12144 
   12145 
   12146 void HOptimizedGraphBuilder::VisitExportDeclaration(
   12147     ExportDeclaration* declaration) {
   12148   UNREACHABLE();
   12149 }
   12150 
   12151 
   12152 void HOptimizedGraphBuilder::VisitRewritableAssignmentExpression(
   12153     RewritableAssignmentExpression* node) {
   12154   CHECK_ALIVE(Visit(node->expression()));
   12155 }
   12156 
   12157 
   12158 // Generators for inline runtime functions.
   12159 // Support for types.
   12160 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
   12161   DCHECK(call->arguments()->length() == 1);
   12162   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12163   HValue* value = Pop();
   12164   HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
   12165   return ast_context()->ReturnControl(result, call->id());
   12166 }
   12167 
   12168 
   12169 void HOptimizedGraphBuilder::GenerateIsJSReceiver(CallRuntime* call) {
   12170   DCHECK(call->arguments()->length() == 1);
   12171   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12172   HValue* value = Pop();
   12173   HHasInstanceTypeAndBranch* result =
   12174       New<HHasInstanceTypeAndBranch>(value,
   12175                                      FIRST_JS_RECEIVER_TYPE,
   12176                                      LAST_JS_RECEIVER_TYPE);
   12177   return ast_context()->ReturnControl(result, call->id());
   12178 }
   12179 
   12180 
   12181 void HOptimizedGraphBuilder::GenerateIsFunction(CallRuntime* call) {
   12182   DCHECK(call->arguments()->length() == 1);
   12183   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12184   HValue* value = Pop();
   12185   HHasInstanceTypeAndBranch* result = New<HHasInstanceTypeAndBranch>(
   12186       value, FIRST_FUNCTION_TYPE, LAST_FUNCTION_TYPE);
   12187   return ast_context()->ReturnControl(result, call->id());
   12188 }
   12189 
   12190 
   12191 void HOptimizedGraphBuilder::GenerateIsMinusZero(CallRuntime* call) {
   12192   DCHECK(call->arguments()->length() == 1);
   12193   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12194   HValue* value = Pop();
   12195   HCompareMinusZeroAndBranch* result = New<HCompareMinusZeroAndBranch>(value);
   12196   return ast_context()->ReturnControl(result, call->id());
   12197 }
   12198 
   12199 
   12200 void HOptimizedGraphBuilder::GenerateHasCachedArrayIndex(CallRuntime* call) {
   12201   DCHECK(call->arguments()->length() == 1);
   12202   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12203   HValue* value = Pop();
   12204   HHasCachedArrayIndexAndBranch* result =
   12205       New<HHasCachedArrayIndexAndBranch>(value);
   12206   return ast_context()->ReturnControl(result, call->id());
   12207 }
   12208 
   12209 
   12210 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
   12211   DCHECK(call->arguments()->length() == 1);
   12212   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12213   HValue* value = Pop();
   12214   HHasInstanceTypeAndBranch* result =
   12215       New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
   12216   return ast_context()->ReturnControl(result, call->id());
   12217 }
   12218 
   12219 
   12220 void HOptimizedGraphBuilder::GenerateIsTypedArray(CallRuntime* call) {
   12221   DCHECK(call->arguments()->length() == 1);
   12222   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12223   HValue* value = Pop();
   12224   HHasInstanceTypeAndBranch* result =
   12225       New<HHasInstanceTypeAndBranch>(value, JS_TYPED_ARRAY_TYPE);
   12226   return ast_context()->ReturnControl(result, call->id());
   12227 }
   12228 
   12229 
   12230 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
   12231   DCHECK(call->arguments()->length() == 1);
   12232   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12233   HValue* value = Pop();
   12234   HHasInstanceTypeAndBranch* result =
   12235       New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE);
   12236   return ast_context()->ReturnControl(result, call->id());
   12237 }
   12238 
   12239 
   12240 void HOptimizedGraphBuilder::GenerateToInteger(CallRuntime* call) {
   12241   DCHECK_EQ(1, call->arguments()->length());
   12242   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12243   HValue* input = Pop();
   12244   if (input->type().IsSmi()) {
   12245     return ast_context()->ReturnValue(input);
   12246   } else {
   12247     IfBuilder if_inputissmi(this);
   12248     if_inputissmi.If<HIsSmiAndBranch>(input);
   12249     if_inputissmi.Then();
   12250     {
   12251       // Return the input value.
   12252       Push(input);
   12253       Add<HSimulate>(call->id(), FIXED_SIMULATE);
   12254     }
   12255     if_inputissmi.Else();
   12256     {
   12257       Add<HPushArguments>(input);
   12258       Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kToInteger), 1));
   12259       Add<HSimulate>(call->id(), FIXED_SIMULATE);
   12260     }
   12261     if_inputissmi.End();
   12262     return ast_context()->ReturnValue(Pop());
   12263   }
   12264 }
   12265 
   12266 
   12267 void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
   12268   DCHECK_EQ(1, call->arguments()->length());
   12269   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12270   HValue* value = Pop();
   12271   HValue* result = BuildToObject(value);
   12272   return ast_context()->ReturnValue(result);
   12273 }
   12274 
   12275 
   12276 void HOptimizedGraphBuilder::GenerateToString(CallRuntime* call) {
   12277   DCHECK_EQ(1, call->arguments()->length());
   12278   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12279   Callable callable = CodeFactory::ToString(isolate());
   12280   HValue* input = Pop();
   12281   if (input->type().IsString()) {
   12282     return ast_context()->ReturnValue(input);
   12283   } else {
   12284     HValue* stub = Add<HConstant>(callable.code());
   12285     HValue* values[] = {context(), input};
   12286     HInstruction* result =
   12287         New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
   12288                                  Vector<HValue*>(values, arraysize(values)));
   12289     return ast_context()->ReturnInstruction(result, call->id());
   12290   }
   12291 }
   12292 
   12293 
   12294 void HOptimizedGraphBuilder::GenerateToLength(CallRuntime* call) {
   12295   DCHECK_EQ(1, call->arguments()->length());
   12296   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12297   Callable callable = CodeFactory::ToLength(isolate());
   12298   HValue* input = Pop();
   12299   HValue* stub = Add<HConstant>(callable.code());
   12300   HValue* values[] = {context(), input};
   12301   HInstruction* result =
   12302       New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
   12303                                Vector<HValue*>(values, arraysize(values)));
   12304   return ast_context()->ReturnInstruction(result, call->id());
   12305 }
   12306 
   12307 
   12308 void HOptimizedGraphBuilder::GenerateToNumber(CallRuntime* call) {
   12309   DCHECK_EQ(1, call->arguments()->length());
   12310   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12311   Callable callable = CodeFactory::ToNumber(isolate());
   12312   HValue* input = Pop();
   12313   if (input->type().IsTaggedNumber()) {
   12314     return ast_context()->ReturnValue(input);
   12315   } else {
   12316     HValue* stub = Add<HConstant>(callable.code());
   12317     HValue* values[] = {context(), input};
   12318     HInstruction* result =
   12319         New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
   12320                                  Vector<HValue*>(values, arraysize(values)));
   12321     return ast_context()->ReturnInstruction(result, call->id());
   12322   }
   12323 }
   12324 
   12325 
   12326 void HOptimizedGraphBuilder::GenerateIsJSProxy(CallRuntime* call) {
   12327   DCHECK(call->arguments()->length() == 1);
   12328   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12329   HValue* value = Pop();
   12330   HIfContinuation continuation;
   12331   IfBuilder if_proxy(this);
   12332 
   12333   HValue* smicheck = if_proxy.IfNot<HIsSmiAndBranch>(value);
   12334   if_proxy.And();
   12335   HValue* map = Add<HLoadNamedField>(value, smicheck, HObjectAccess::ForMap());
   12336   HValue* instance_type =
   12337       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
   12338   if_proxy.If<HCompareNumericAndBranch>(
   12339       instance_type, Add<HConstant>(JS_PROXY_TYPE), Token::EQ);
   12340 
   12341   if_proxy.CaptureContinuation(&continuation);
   12342   return ast_context()->ReturnContinuation(&continuation, call->id());
   12343 }
   12344 
   12345 
   12346 void HOptimizedGraphBuilder::GenerateHasFastPackedElements(CallRuntime* call) {
   12347   DCHECK(call->arguments()->length() == 1);
   12348   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12349   HValue* object = Pop();
   12350   HIfContinuation continuation(graph()->CreateBasicBlock(),
   12351                                graph()->CreateBasicBlock());
   12352   IfBuilder if_not_smi(this);
   12353   if_not_smi.IfNot<HIsSmiAndBranch>(object);
   12354   if_not_smi.Then();
   12355   {
   12356     NoObservableSideEffectsScope no_effects(this);
   12357 
   12358     IfBuilder if_fast_packed(this);
   12359     HValue* elements_kind = BuildGetElementsKind(object);
   12360     if_fast_packed.If<HCompareNumericAndBranch>(
   12361         elements_kind, Add<HConstant>(FAST_SMI_ELEMENTS), Token::EQ);
   12362     if_fast_packed.Or();
   12363     if_fast_packed.If<HCompareNumericAndBranch>(
   12364         elements_kind, Add<HConstant>(FAST_ELEMENTS), Token::EQ);
   12365     if_fast_packed.Or();
   12366     if_fast_packed.If<HCompareNumericAndBranch>(
   12367         elements_kind, Add<HConstant>(FAST_DOUBLE_ELEMENTS), Token::EQ);
   12368     if_fast_packed.JoinContinuation(&continuation);
   12369   }
   12370   if_not_smi.JoinContinuation(&continuation);
   12371   return ast_context()->ReturnContinuation(&continuation, call->id());
   12372 }
   12373 
   12374 
   12375 // Support for arguments.length and arguments[?].
   12376 void HOptimizedGraphBuilder::GenerateArgumentsLength(CallRuntime* call) {
   12377   DCHECK(call->arguments()->length() == 0);
   12378   HInstruction* result = NULL;
   12379   if (function_state()->outer() == NULL) {
   12380     HInstruction* elements = Add<HArgumentsElements>(false);
   12381     result = New<HArgumentsLength>(elements);
   12382   } else {
   12383     // Number of arguments without receiver.
   12384     int argument_count = environment()->
   12385         arguments_environment()->parameter_count() - 1;
   12386     result = New<HConstant>(argument_count);
   12387   }
   12388   return ast_context()->ReturnInstruction(result, call->id());
   12389 }
   12390 
   12391 
   12392 void HOptimizedGraphBuilder::GenerateArguments(CallRuntime* call) {
   12393   DCHECK(call->arguments()->length() == 1);
   12394   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12395   HValue* index = Pop();
   12396   HInstruction* result = NULL;
   12397   if (function_state()->outer() == NULL) {
   12398     HInstruction* elements = Add<HArgumentsElements>(false);
   12399     HInstruction* length = Add<HArgumentsLength>(elements);
   12400     HInstruction* checked_index = Add<HBoundsCheck>(index, length);
   12401     result = New<HAccessArgumentsAt>(elements, length, checked_index);
   12402   } else {
   12403     EnsureArgumentsArePushedForAccess();
   12404 
   12405     // Number of arguments without receiver.
   12406     HInstruction* elements = function_state()->arguments_elements();
   12407     int argument_count = environment()->
   12408         arguments_environment()->parameter_count() - 1;
   12409     HInstruction* length = Add<HConstant>(argument_count);
   12410     HInstruction* checked_key = Add<HBoundsCheck>(index, length);
   12411     result = New<HAccessArgumentsAt>(elements, length, checked_key);
   12412   }
   12413   return ast_context()->ReturnInstruction(result, call->id());
   12414 }
   12415 
   12416 
   12417 void HOptimizedGraphBuilder::GenerateValueOf(CallRuntime* call) {
   12418   DCHECK(call->arguments()->length() == 1);
   12419   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12420   HValue* object = Pop();
   12421 
   12422   IfBuilder if_objectisvalue(this);
   12423   HValue* objectisvalue = if_objectisvalue.If<HHasInstanceTypeAndBranch>(
   12424       object, JS_VALUE_TYPE);
   12425   if_objectisvalue.Then();
   12426   {
   12427     // Return the actual value.
   12428     Push(Add<HLoadNamedField>(
   12429             object, objectisvalue,
   12430             HObjectAccess::ForObservableJSObjectOffset(
   12431                 JSValue::kValueOffset)));
   12432     Add<HSimulate>(call->id(), FIXED_SIMULATE);
   12433   }
   12434   if_objectisvalue.Else();
   12435   {
   12436     // If the object is not a value return the object.
   12437     Push(object);
   12438     Add<HSimulate>(call->id(), FIXED_SIMULATE);
   12439   }
   12440   if_objectisvalue.End();
   12441   return ast_context()->ReturnValue(Pop());
   12442 }
   12443 
   12444 
   12445 void HOptimizedGraphBuilder::GenerateJSValueGetValue(CallRuntime* call) {
   12446   DCHECK(call->arguments()->length() == 1);
   12447   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12448   HValue* value = Pop();
   12449   HInstruction* result = Add<HLoadNamedField>(
   12450       value, nullptr,
   12451       HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset));
   12452   return ast_context()->ReturnInstruction(result, call->id());
   12453 }
   12454 
   12455 
   12456 void HOptimizedGraphBuilder::GenerateIsDate(CallRuntime* call) {
   12457   DCHECK_EQ(1, call->arguments()->length());
   12458   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12459   HValue* value = Pop();
   12460   HHasInstanceTypeAndBranch* result =
   12461       New<HHasInstanceTypeAndBranch>(value, JS_DATE_TYPE);
   12462   return ast_context()->ReturnControl(result, call->id());
   12463 }
   12464 
   12465 
   12466 void HOptimizedGraphBuilder::GenerateOneByteSeqStringSetChar(
   12467     CallRuntime* call) {
   12468   DCHECK(call->arguments()->length() == 3);
   12469   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12470   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12471   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
   12472   HValue* string = Pop();
   12473   HValue* value = Pop();
   12474   HValue* index = Pop();
   12475   Add<HSeqStringSetChar>(String::ONE_BYTE_ENCODING, string,
   12476                          index, value);
   12477   Add<HSimulate>(call->id(), FIXED_SIMULATE);
   12478   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12479 }
   12480 
   12481 
   12482 void HOptimizedGraphBuilder::GenerateTwoByteSeqStringSetChar(
   12483     CallRuntime* call) {
   12484   DCHECK(call->arguments()->length() == 3);
   12485   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12486   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12487   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
   12488   HValue* string = Pop();
   12489   HValue* value = Pop();
   12490   HValue* index = Pop();
   12491   Add<HSeqStringSetChar>(String::TWO_BYTE_ENCODING, string,
   12492                          index, value);
   12493   Add<HSimulate>(call->id(), FIXED_SIMULATE);
   12494   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12495 }
   12496 
   12497 
   12498 void HOptimizedGraphBuilder::GenerateSetValueOf(CallRuntime* call) {
   12499   DCHECK(call->arguments()->length() == 2);
   12500   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12501   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12502   HValue* value = Pop();
   12503   HValue* object = Pop();
   12504 
   12505   // Check if object is a JSValue.
   12506   IfBuilder if_objectisvalue(this);
   12507   if_objectisvalue.If<HHasInstanceTypeAndBranch>(object, JS_VALUE_TYPE);
   12508   if_objectisvalue.Then();
   12509   {
   12510     // Create in-object property store to kValueOffset.
   12511     Add<HStoreNamedField>(object,
   12512         HObjectAccess::ForObservableJSObjectOffset(JSValue::kValueOffset),
   12513         value);
   12514     if (!ast_context()->IsEffect()) {
   12515       Push(value);
   12516     }
   12517     Add<HSimulate>(call->id(), FIXED_SIMULATE);
   12518   }
   12519   if_objectisvalue.Else();
   12520   {
   12521     // Nothing to do in this case.
   12522     if (!ast_context()->IsEffect()) {
   12523       Push(value);
   12524     }
   12525     Add<HSimulate>(call->id(), FIXED_SIMULATE);
   12526   }
   12527   if_objectisvalue.End();
   12528   if (!ast_context()->IsEffect()) {
   12529     Drop(1);
   12530   }
   12531   return ast_context()->ReturnValue(value);
   12532 }
   12533 
   12534 
   12535 // Fast support for charCodeAt(n).
   12536 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
   12537   DCHECK(call->arguments()->length() == 2);
   12538   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12539   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12540   HValue* index = Pop();
   12541   HValue* string = Pop();
   12542   HInstruction* result = BuildStringCharCodeAt(string, index);
   12543   return ast_context()->ReturnInstruction(result, call->id());
   12544 }
   12545 
   12546 
   12547 // Fast support for string.charAt(n) and string[n].
   12548 void HOptimizedGraphBuilder::GenerateStringCharFromCode(CallRuntime* call) {
   12549   DCHECK(call->arguments()->length() == 1);
   12550   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12551   HValue* char_code = Pop();
   12552   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
   12553   return ast_context()->ReturnInstruction(result, call->id());
   12554 }
   12555 
   12556 
   12557 // Fast support for string.charAt(n) and string[n].
   12558 void HOptimizedGraphBuilder::GenerateStringCharAt(CallRuntime* call) {
   12559   DCHECK(call->arguments()->length() == 2);
   12560   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12561   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12562   HValue* index = Pop();
   12563   HValue* string = Pop();
   12564   HInstruction* char_code = BuildStringCharCodeAt(string, index);
   12565   AddInstruction(char_code);
   12566   HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
   12567   return ast_context()->ReturnInstruction(result, call->id());
   12568 }
   12569 
   12570 
   12571 // Fast support for object equality testing.
   12572 void HOptimizedGraphBuilder::GenerateObjectEquals(CallRuntime* call) {
   12573   DCHECK(call->arguments()->length() == 2);
   12574   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12575   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12576   HValue* right = Pop();
   12577   HValue* left = Pop();
   12578   HCompareObjectEqAndBranch* result =
   12579       New<HCompareObjectEqAndBranch>(left, right);
   12580   return ast_context()->ReturnControl(result, call->id());
   12581 }
   12582 
   12583 
   12584 // Fast support for SubString.
   12585 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
   12586   DCHECK_EQ(3, call->arguments()->length());
   12587   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12588   PushArgumentsFromEnvironment(call->arguments()->length());
   12589   HCallStub* result = New<HCallStub>(CodeStub::SubString, 3);
   12590   return ast_context()->ReturnInstruction(result, call->id());
   12591 }
   12592 
   12593 
   12594 // Support for direct calls from JavaScript to native RegExp code.
   12595 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
   12596   DCHECK_EQ(4, call->arguments()->length());
   12597   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12598   PushArgumentsFromEnvironment(call->arguments()->length());
   12599   HCallStub* result = New<HCallStub>(CodeStub::RegExpExec, 4);
   12600   return ast_context()->ReturnInstruction(result, call->id());
   12601 }
   12602 
   12603 
   12604 void HOptimizedGraphBuilder::GenerateRegExpFlags(CallRuntime* call) {
   12605   DCHECK_EQ(1, call->arguments()->length());
   12606   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12607   HValue* regexp = Pop();
   12608   HInstruction* result =
   12609       New<HLoadNamedField>(regexp, nullptr, HObjectAccess::ForJSRegExpFlags());
   12610   return ast_context()->ReturnInstruction(result, call->id());
   12611 }
   12612 
   12613 
   12614 void HOptimizedGraphBuilder::GenerateRegExpSource(CallRuntime* call) {
   12615   DCHECK_EQ(1, call->arguments()->length());
   12616   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12617   HValue* regexp = Pop();
   12618   HInstruction* result =
   12619       New<HLoadNamedField>(regexp, nullptr, HObjectAccess::ForJSRegExpSource());
   12620   return ast_context()->ReturnInstruction(result, call->id());
   12621 }
   12622 
   12623 
   12624 void HOptimizedGraphBuilder::GenerateDoubleLo(CallRuntime* call) {
   12625   DCHECK_EQ(1, call->arguments()->length());
   12626   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12627   HValue* value = Pop();
   12628   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::LOW);
   12629   return ast_context()->ReturnInstruction(result, call->id());
   12630 }
   12631 
   12632 
   12633 void HOptimizedGraphBuilder::GenerateDoubleHi(CallRuntime* call) {
   12634   DCHECK_EQ(1, call->arguments()->length());
   12635   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12636   HValue* value = Pop();
   12637   HInstruction* result = NewUncasted<HDoubleBits>(value, HDoubleBits::HIGH);
   12638   return ast_context()->ReturnInstruction(result, call->id());
   12639 }
   12640 
   12641 
   12642 void HOptimizedGraphBuilder::GenerateConstructDouble(CallRuntime* call) {
   12643   DCHECK_EQ(2, call->arguments()->length());
   12644   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12645   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12646   HValue* lo = Pop();
   12647   HValue* hi = Pop();
   12648   HInstruction* result = NewUncasted<HConstructDouble>(hi, lo);
   12649   return ast_context()->ReturnInstruction(result, call->id());
   12650 }
   12651 
   12652 
   12653 // Construct a RegExp exec result with two in-object properties.
   12654 void HOptimizedGraphBuilder::GenerateRegExpConstructResult(CallRuntime* call) {
   12655   DCHECK_EQ(3, call->arguments()->length());
   12656   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12657   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12658   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
   12659   HValue* input = Pop();
   12660   HValue* index = Pop();
   12661   HValue* length = Pop();
   12662   HValue* result = BuildRegExpConstructResult(length, index, input);
   12663   return ast_context()->ReturnValue(result);
   12664 }
   12665 
   12666 
   12667 // Fast support for number to string.
   12668 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
   12669   DCHECK_EQ(1, call->arguments()->length());
   12670   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12671   HValue* number = Pop();
   12672   HValue* result = BuildNumberToString(number, Type::Any(zone()));
   12673   return ast_context()->ReturnValue(result);
   12674 }
   12675 
   12676 
   12677 // Fast support for calls.
   12678 void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) {
   12679   DCHECK_LE(2, call->arguments()->length());
   12680   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12681   CallTrampolineDescriptor descriptor(isolate());
   12682   PushArgumentsFromEnvironment(call->arguments()->length() - 1);
   12683   HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call());
   12684   HValue* target = Pop();
   12685   HValue* values[] = {context(), target,
   12686                       Add<HConstant>(call->arguments()->length() - 2)};
   12687   HInstruction* result = New<HCallWithDescriptor>(
   12688       trampoline, call->arguments()->length() - 1, descriptor,
   12689       Vector<HValue*>(values, arraysize(values)));
   12690   return ast_context()->ReturnInstruction(result, call->id());
   12691 }
   12692 
   12693 
   12694 // Fast call to math functions.
   12695 void HOptimizedGraphBuilder::GenerateMathPow(CallRuntime* call) {
   12696   DCHECK_EQ(2, call->arguments()->length());
   12697   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12698   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12699   HValue* right = Pop();
   12700   HValue* left = Pop();
   12701   HInstruction* result = NewUncasted<HPower>(left, right);
   12702   return ast_context()->ReturnInstruction(result, call->id());
   12703 }
   12704 
   12705 
   12706 void HOptimizedGraphBuilder::GenerateMathClz32(CallRuntime* call) {
   12707   DCHECK(call->arguments()->length() == 1);
   12708   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12709   HValue* value = Pop();
   12710   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathClz32);
   12711   return ast_context()->ReturnInstruction(result, call->id());
   12712 }
   12713 
   12714 
   12715 void HOptimizedGraphBuilder::GenerateMathFloor(CallRuntime* call) {
   12716   DCHECK(call->arguments()->length() == 1);
   12717   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12718   HValue* value = Pop();
   12719   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathFloor);
   12720   return ast_context()->ReturnInstruction(result, call->id());
   12721 }
   12722 
   12723 
   12724 void HOptimizedGraphBuilder::GenerateMathLogRT(CallRuntime* call) {
   12725   DCHECK(call->arguments()->length() == 1);
   12726   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12727   HValue* value = Pop();
   12728   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathLog);
   12729   return ast_context()->ReturnInstruction(result, call->id());
   12730 }
   12731 
   12732 
   12733 void HOptimizedGraphBuilder::GenerateMathSqrt(CallRuntime* call) {
   12734   DCHECK(call->arguments()->length() == 1);
   12735   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12736   HValue* value = Pop();
   12737   HInstruction* result = NewUncasted<HUnaryMathOperation>(value, kMathSqrt);
   12738   return ast_context()->ReturnInstruction(result, call->id());
   12739 }
   12740 
   12741 
   12742 void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) {
   12743   DCHECK(call->arguments()->length() == 2);
   12744   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12745   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12746   HValue* index = Pop();
   12747   HValue* object = Pop();
   12748   HInstruction* result = New<HLoadKeyed>(
   12749       object, index, nullptr, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
   12750   return ast_context()->ReturnInstruction(result, call->id());
   12751 }
   12752 
   12753 
   12754 void HOptimizedGraphBuilder::GenerateFixedArraySet(CallRuntime* call) {
   12755   DCHECK(call->arguments()->length() == 3);
   12756   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12757   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12758   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
   12759   HValue* value = Pop();
   12760   HValue* index = Pop();
   12761   HValue* object = Pop();
   12762   NoObservableSideEffectsScope no_effects(this);
   12763   Add<HStoreKeyed>(object, index, value, nullptr, FAST_HOLEY_ELEMENTS);
   12764   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12765 }
   12766 
   12767 
   12768 void HOptimizedGraphBuilder::GenerateTheHole(CallRuntime* call) {
   12769   DCHECK(call->arguments()->length() == 0);
   12770   return ast_context()->ReturnValue(graph()->GetConstantHole());
   12771 }
   12772 
   12773 
   12774 void HOptimizedGraphBuilder::GenerateCreateIterResultObject(CallRuntime* call) {
   12775   DCHECK_EQ(2, call->arguments()->length());
   12776   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12777   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12778   HValue* done = Pop();
   12779   HValue* value = Pop();
   12780   HValue* result = BuildCreateIterResultObject(value, done);
   12781   return ast_context()->ReturnValue(result);
   12782 }
   12783 
   12784 
   12785 void HOptimizedGraphBuilder::GenerateJSCollectionGetTable(CallRuntime* call) {
   12786   DCHECK(call->arguments()->length() == 1);
   12787   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12788   HValue* receiver = Pop();
   12789   HInstruction* result = New<HLoadNamedField>(
   12790       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
   12791   return ast_context()->ReturnInstruction(result, call->id());
   12792 }
   12793 
   12794 
   12795 void HOptimizedGraphBuilder::GenerateStringGetRawHashField(CallRuntime* call) {
   12796   DCHECK(call->arguments()->length() == 1);
   12797   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12798   HValue* object = Pop();
   12799   HInstruction* result = New<HLoadNamedField>(
   12800       object, nullptr, HObjectAccess::ForStringHashField());
   12801   return ast_context()->ReturnInstruction(result, call->id());
   12802 }
   12803 
   12804 
   12805 template <typename CollectionType>
   12806 HValue* HOptimizedGraphBuilder::BuildAllocateOrderedHashTable() {
   12807   static const int kCapacity = CollectionType::kMinCapacity;
   12808   static const int kBucketCount = kCapacity / CollectionType::kLoadFactor;
   12809   static const int kFixedArrayLength = CollectionType::kHashTableStartIndex +
   12810                                        kBucketCount +
   12811                                        (kCapacity * CollectionType::kEntrySize);
   12812   static const int kSizeInBytes =
   12813       FixedArray::kHeaderSize + (kFixedArrayLength * kPointerSize);
   12814 
   12815   // Allocate the table and add the proper map.
   12816   HValue* table =
   12817       Add<HAllocate>(Add<HConstant>(kSizeInBytes), HType::HeapObject(),
   12818                      NOT_TENURED, FIXED_ARRAY_TYPE);
   12819   AddStoreMapConstant(table, isolate()->factory()->ordered_hash_table_map());
   12820 
   12821   // Initialize the FixedArray...
   12822   HValue* length = Add<HConstant>(kFixedArrayLength);
   12823   Add<HStoreNamedField>(table, HObjectAccess::ForFixedArrayLength(), length);
   12824 
   12825   // ...and the OrderedHashTable fields.
   12826   Add<HStoreNamedField>(
   12827       table,
   12828       HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>(),
   12829       Add<HConstant>(kBucketCount));
   12830   Add<HStoreNamedField>(
   12831       table,
   12832       HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(),
   12833       graph()->GetConstant0());
   12834   Add<HStoreNamedField>(
   12835       table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
   12836                  CollectionType>(),
   12837       graph()->GetConstant0());
   12838 
   12839   // Fill the buckets with kNotFound.
   12840   HValue* not_found = Add<HConstant>(CollectionType::kNotFound);
   12841   for (int i = 0; i < kBucketCount; ++i) {
   12842     Add<HStoreNamedField>(
   12843         table, HObjectAccess::ForOrderedHashTableBucket<CollectionType>(i),
   12844         not_found);
   12845   }
   12846 
   12847   // Fill the data table with undefined.
   12848   HValue* undefined = graph()->GetConstantUndefined();
   12849   for (int i = 0; i < (kCapacity * CollectionType::kEntrySize); ++i) {
   12850     Add<HStoreNamedField>(table,
   12851                           HObjectAccess::ForOrderedHashTableDataTableIndex<
   12852                               CollectionType, kBucketCount>(i),
   12853                           undefined);
   12854   }
   12855 
   12856   return table;
   12857 }
   12858 
   12859 
   12860 void HOptimizedGraphBuilder::GenerateSetInitialize(CallRuntime* call) {
   12861   DCHECK(call->arguments()->length() == 1);
   12862   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12863   HValue* receiver = Pop();
   12864 
   12865   NoObservableSideEffectsScope no_effects(this);
   12866   HValue* table = BuildAllocateOrderedHashTable<OrderedHashSet>();
   12867   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
   12868   return ast_context()->ReturnValue(receiver);
   12869 }
   12870 
   12871 
   12872 void HOptimizedGraphBuilder::GenerateMapInitialize(CallRuntime* call) {
   12873   DCHECK(call->arguments()->length() == 1);
   12874   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12875   HValue* receiver = Pop();
   12876 
   12877   NoObservableSideEffectsScope no_effects(this);
   12878   HValue* table = BuildAllocateOrderedHashTable<OrderedHashMap>();
   12879   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
   12880   return ast_context()->ReturnValue(receiver);
   12881 }
   12882 
   12883 
   12884 template <typename CollectionType>
   12885 void HOptimizedGraphBuilder::BuildOrderedHashTableClear(HValue* receiver) {
   12886   HValue* old_table = Add<HLoadNamedField>(
   12887       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
   12888   HValue* new_table = BuildAllocateOrderedHashTable<CollectionType>();
   12889   Add<HStoreNamedField>(
   12890       old_table, HObjectAccess::ForOrderedHashTableNextTable<CollectionType>(),
   12891       new_table);
   12892   Add<HStoreNamedField>(
   12893       old_table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
   12894                      CollectionType>(),
   12895       Add<HConstant>(CollectionType::kClearedTableSentinel));
   12896   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(),
   12897                         new_table);
   12898 }
   12899 
   12900 
   12901 void HOptimizedGraphBuilder::GenerateSetClear(CallRuntime* call) {
   12902   DCHECK(call->arguments()->length() == 1);
   12903   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12904   HValue* receiver = Pop();
   12905 
   12906   NoObservableSideEffectsScope no_effects(this);
   12907   BuildOrderedHashTableClear<OrderedHashSet>(receiver);
   12908   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12909 }
   12910 
   12911 
   12912 void HOptimizedGraphBuilder::GenerateMapClear(CallRuntime* call) {
   12913   DCHECK(call->arguments()->length() == 1);
   12914   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12915   HValue* receiver = Pop();
   12916 
   12917   NoObservableSideEffectsScope no_effects(this);
   12918   BuildOrderedHashTableClear<OrderedHashMap>(receiver);
   12919   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12920 }
   12921 
   12922 
   12923 void HOptimizedGraphBuilder::GenerateGetCachedArrayIndex(CallRuntime* call) {
   12924   DCHECK(call->arguments()->length() == 1);
   12925   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12926   HValue* value = Pop();
   12927   HGetCachedArrayIndex* result = New<HGetCachedArrayIndex>(value);
   12928   return ast_context()->ReturnInstruction(result, call->id());
   12929 }
   12930 
   12931 
   12932 void HOptimizedGraphBuilder::GenerateFastOneByteArrayJoin(CallRuntime* call) {
   12933   // Simply returning undefined here would be semantically correct and even
   12934   // avoid the bailout. Nevertheless, some ancient benchmarks like SunSpider's
   12935   // string-fasta would tank, because fullcode contains an optimized version.
   12936   // Obviously the fullcode => Crankshaft => bailout => fullcode dance is
   12937   // faster... *sigh*
   12938   return Bailout(kInlinedRuntimeFunctionFastOneByteArrayJoin);
   12939 }
   12940 
   12941 
   12942 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
   12943     CallRuntime* call) {
   12944   Add<HDebugBreak>();
   12945   return ast_context()->ReturnValue(graph()->GetConstant0());
   12946 }
   12947 
   12948 
   12949 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
   12950   DCHECK(call->arguments()->length() == 0);
   12951   HValue* ref =
   12952       Add<HConstant>(ExternalReference::debug_is_active_address(isolate()));
   12953   HValue* value =
   12954       Add<HLoadNamedField>(ref, nullptr, HObjectAccess::ForExternalUInteger8());
   12955   return ast_context()->ReturnValue(value);
   12956 }
   12957 
   12958 
   12959 #undef CHECK_BAILOUT
   12960 #undef CHECK_ALIVE
   12961 
   12962 
   12963 HEnvironment::HEnvironment(HEnvironment* outer,
   12964                            Scope* scope,
   12965                            Handle<JSFunction> closure,
   12966                            Zone* zone)
   12967     : closure_(closure),
   12968       values_(0, zone),
   12969       frame_type_(JS_FUNCTION),
   12970       parameter_count_(0),
   12971       specials_count_(1),
   12972       local_count_(0),
   12973       outer_(outer),
   12974       entry_(NULL),
   12975       pop_count_(0),
   12976       push_count_(0),
   12977       ast_id_(BailoutId::None()),
   12978       zone_(zone) {
   12979   Scope* declaration_scope = scope->DeclarationScope();
   12980   Initialize(declaration_scope->num_parameters() + 1,
   12981              declaration_scope->num_stack_slots(), 0);
   12982 }
   12983 
   12984 
   12985 HEnvironment::HEnvironment(Zone* zone, int parameter_count)
   12986     : values_(0, zone),
   12987       frame_type_(STUB),
   12988       parameter_count_(parameter_count),
   12989       specials_count_(1),
   12990       local_count_(0),
   12991       outer_(NULL),
   12992       entry_(NULL),
   12993       pop_count_(0),
   12994       push_count_(0),
   12995       ast_id_(BailoutId::None()),
   12996       zone_(zone) {
   12997   Initialize(parameter_count, 0, 0);
   12998 }
   12999 
   13000 
   13001 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
   13002     : values_(0, zone),
   13003       frame_type_(JS_FUNCTION),
   13004       parameter_count_(0),
   13005       specials_count_(0),
   13006       local_count_(0),
   13007       outer_(NULL),
   13008       entry_(NULL),
   13009       pop_count_(0),
   13010       push_count_(0),
   13011       ast_id_(other->ast_id()),
   13012       zone_(zone) {
   13013   Initialize(other);
   13014 }
   13015 
   13016 
   13017 HEnvironment::HEnvironment(HEnvironment* outer,
   13018                            Handle<JSFunction> closure,
   13019                            FrameType frame_type,
   13020                            int arguments,
   13021                            Zone* zone)
   13022     : closure_(closure),
   13023       values_(arguments, zone),
   13024       frame_type_(frame_type),
   13025       parameter_count_(arguments),
   13026       specials_count_(0),
   13027       local_count_(0),
   13028       outer_(outer),
   13029       entry_(NULL),
   13030       pop_count_(0),
   13031       push_count_(0),
   13032       ast_id_(BailoutId::None()),
   13033       zone_(zone) {
   13034 }
   13035 
   13036 
   13037 void HEnvironment::Initialize(int parameter_count,
   13038                               int local_count,
   13039                               int stack_height) {
   13040   parameter_count_ = parameter_count;
   13041   local_count_ = local_count;
   13042 
   13043   // Avoid reallocating the temporaries' backing store on the first Push.
   13044   int total = parameter_count + specials_count_ + local_count + stack_height;
   13045   values_.Initialize(total + 4, zone());
   13046   for (int i = 0; i < total; ++i) values_.Add(NULL, zone());
   13047 }
   13048 
   13049 
   13050 void HEnvironment::Initialize(const HEnvironment* other) {
   13051   closure_ = other->closure();
   13052   values_.AddAll(other->values_, zone());
   13053   assigned_variables_.Union(other->assigned_variables_, zone());
   13054   frame_type_ = other->frame_type_;
   13055   parameter_count_ = other->parameter_count_;
   13056   local_count_ = other->local_count_;
   13057   if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
   13058   entry_ = other->entry_;
   13059   pop_count_ = other->pop_count_;
   13060   push_count_ = other->push_count_;
   13061   specials_count_ = other->specials_count_;
   13062   ast_id_ = other->ast_id_;
   13063 }
   13064 
   13065 
   13066 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
   13067   DCHECK(!block->IsLoopHeader());
   13068   DCHECK(values_.length() == other->values_.length());
   13069 
   13070   int length = values_.length();
   13071   for (int i = 0; i < length; ++i) {
   13072     HValue* value = values_[i];
   13073     if (value != NULL && value->IsPhi() && value->block() == block) {
   13074       // There is already a phi for the i'th value.
   13075       HPhi* phi = HPhi::cast(value);
   13076       // Assert index is correct and that we haven't missed an incoming edge.
   13077       DCHECK(phi->merged_index() == i || !phi->HasMergedIndex());
   13078       DCHECK(phi->OperandCount() == block->predecessors()->length());
   13079       phi->AddInput(other->values_[i]);
   13080     } else if (values_[i] != other->values_[i]) {
   13081       // There is a fresh value on the incoming edge, a phi is needed.
   13082       DCHECK(values_[i] != NULL && other->values_[i] != NULL);
   13083       HPhi* phi = block->AddNewPhi(i);
   13084       HValue* old_value = values_[i];
   13085       for (int j = 0; j < block->predecessors()->length(); j++) {
   13086         phi->AddInput(old_value);
   13087       }
   13088       phi->AddInput(other->values_[i]);
   13089       this->values_[i] = phi;
   13090     }
   13091   }
   13092 }
   13093 
   13094 
   13095 void HEnvironment::Bind(int index, HValue* value) {
   13096   DCHECK(value != NULL);
   13097   assigned_variables_.Add(index, zone());
   13098   values_[index] = value;
   13099 }
   13100 
   13101 
   13102 bool HEnvironment::HasExpressionAt(int index) const {
   13103   return index >= parameter_count_ + specials_count_ + local_count_;
   13104 }
   13105 
   13106 
   13107 bool HEnvironment::ExpressionStackIsEmpty() const {
   13108   DCHECK(length() >= first_expression_index());
   13109   return length() == first_expression_index();
   13110 }
   13111 
   13112 
   13113 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
   13114   int count = index_from_top + 1;
   13115   int index = values_.length() - count;
   13116   DCHECK(HasExpressionAt(index));
   13117   // The push count must include at least the element in question or else
   13118   // the new value will not be included in this environment's history.
   13119   if (push_count_ < count) {
   13120     // This is the same effect as popping then re-pushing 'count' elements.
   13121     pop_count_ += (count - push_count_);
   13122     push_count_ = count;
   13123   }
   13124   values_[index] = value;
   13125 }
   13126 
   13127 
   13128 HValue* HEnvironment::RemoveExpressionStackAt(int index_from_top) {
   13129   int count = index_from_top + 1;
   13130   int index = values_.length() - count;
   13131   DCHECK(HasExpressionAt(index));
   13132   // Simulate popping 'count' elements and then
   13133   // pushing 'count - 1' elements back.
   13134   pop_count_ += Max(count - push_count_, 0);
   13135   push_count_ = Max(push_count_ - count, 0) + (count - 1);
   13136   return values_.Remove(index);
   13137 }
   13138 
   13139 
   13140 void HEnvironment::Drop(int count) {
   13141   for (int i = 0; i < count; ++i) {
   13142     Pop();
   13143   }
   13144 }
   13145 
   13146 
   13147 void HEnvironment::Print() const {
   13148   OFStream os(stdout);
   13149   os << *this << "\n";
   13150 }
   13151 
   13152 
   13153 HEnvironment* HEnvironment::Copy() const {
   13154   return new(zone()) HEnvironment(this, zone());
   13155 }
   13156 
   13157 
   13158 HEnvironment* HEnvironment::CopyWithoutHistory() const {
   13159   HEnvironment* result = Copy();
   13160   result->ClearHistory();
   13161   return result;
   13162 }
   13163 
   13164 
   13165 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
   13166   HEnvironment* new_env = Copy();
   13167   for (int i = 0; i < values_.length(); ++i) {
   13168     HPhi* phi = loop_header->AddNewPhi(i);
   13169     phi->AddInput(values_[i]);
   13170     new_env->values_[i] = phi;
   13171   }
   13172   new_env->ClearHistory();
   13173   return new_env;
   13174 }
   13175 
   13176 
   13177 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
   13178                                                   Handle<JSFunction> target,
   13179                                                   FrameType frame_type,
   13180                                                   int arguments) const {
   13181   HEnvironment* new_env =
   13182       new(zone()) HEnvironment(outer, target, frame_type,
   13183                                arguments + 1, zone());
   13184   for (int i = 0; i <= arguments; ++i) {  // Include receiver.
   13185     new_env->Push(ExpressionStackAt(arguments - i));
   13186   }
   13187   new_env->ClearHistory();
   13188   return new_env;
   13189 }
   13190 
   13191 
   13192 HEnvironment* HEnvironment::CopyForInlining(
   13193     Handle<JSFunction> target,
   13194     int arguments,
   13195     FunctionLiteral* function,
   13196     HConstant* undefined,
   13197     InliningKind inlining_kind) const {
   13198   DCHECK(frame_type() == JS_FUNCTION);
   13199 
   13200   // Outer environment is a copy of this one without the arguments.
   13201   int arity = function->scope()->num_parameters();
   13202 
   13203   HEnvironment* outer = Copy();
   13204   outer->Drop(arguments + 1);  // Including receiver.
   13205   outer->ClearHistory();
   13206 
   13207   if (inlining_kind == CONSTRUCT_CALL_RETURN) {
   13208     // Create artificial constructor stub environment.  The receiver should
   13209     // actually be the constructor function, but we pass the newly allocated
   13210     // object instead, DoComputeConstructStubFrame() relies on that.
   13211     outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
   13212   } else if (inlining_kind == GETTER_CALL_RETURN) {
   13213     // We need an additional StackFrame::INTERNAL frame for restoring the
   13214     // correct context.
   13215     outer = CreateStubEnvironment(outer, target, JS_GETTER, arguments);
   13216   } else if (inlining_kind == SETTER_CALL_RETURN) {
   13217     // We need an additional StackFrame::INTERNAL frame for temporarily saving
   13218     // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
   13219     outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
   13220   }
   13221 
   13222   if (arity != arguments) {
   13223     // Create artificial arguments adaptation environment.
   13224     outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
   13225   }
   13226 
   13227   HEnvironment* inner =
   13228       new(zone()) HEnvironment(outer, function->scope(), target, zone());
   13229   // Get the argument values from the original environment.
   13230   for (int i = 0; i <= arity; ++i) {  // Include receiver.
   13231     HValue* push = (i <= arguments) ?
   13232         ExpressionStackAt(arguments - i) : undefined;
   13233     inner->SetValueAt(i, push);
   13234   }
   13235   inner->SetValueAt(arity + 1, context());
   13236   for (int i = arity + 2; i < inner->length(); ++i) {
   13237     inner->SetValueAt(i, undefined);
   13238   }
   13239 
   13240   inner->set_ast_id(BailoutId::FunctionEntry());
   13241   return inner;
   13242 }
   13243 
   13244 
   13245 std::ostream& operator<<(std::ostream& os, const HEnvironment& env) {
   13246   for (int i = 0; i < env.length(); i++) {
   13247     if (i == 0) os << "parameters\n";
   13248     if (i == env.parameter_count()) os << "specials\n";
   13249     if (i == env.parameter_count() + env.specials_count()) os << "locals\n";
   13250     if (i == env.parameter_count() + env.specials_count() + env.local_count()) {
   13251       os << "expressions\n";
   13252     }
   13253     HValue* val = env.values()->at(i);
   13254     os << i << ": ";
   13255     if (val != NULL) {
   13256       os << val;
   13257     } else {
   13258       os << "NULL";
   13259     }
   13260     os << "\n";
   13261   }
   13262   return os << "\n";
   13263 }
   13264 
   13265 
   13266 void HTracer::TraceCompilation(CompilationInfo* info) {
   13267   Tag tag(this, "compilation");
   13268   base::SmartArrayPointer<char> name = info->GetDebugName();
   13269   if (info->IsOptimizing()) {
   13270     PrintStringProperty("name", name.get());
   13271     PrintIndent();
   13272     trace_.Add("method \"%s:%d\"\n", name.get(), info->optimization_id());
   13273   } else {
   13274     PrintStringProperty("name", name.get());
   13275     PrintStringProperty("method", "stub");
   13276   }
   13277   PrintLongProperty("date",
   13278                     static_cast<int64_t>(base::OS::TimeCurrentMillis()));
   13279 }
   13280 
   13281 
   13282 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
   13283   DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
   13284   AllowHandleDereference allow_deref;
   13285   AllowDeferredHandleDereference allow_deferred_deref;
   13286   Trace(name, chunk->graph(), chunk);
   13287 }
   13288 
   13289 
   13290 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
   13291   DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
   13292   AllowHandleDereference allow_deref;
   13293   AllowDeferredHandleDereference allow_deferred_deref;
   13294   Trace(name, graph, NULL);
   13295 }
   13296 
   13297 
   13298 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
   13299   Tag tag(this, "cfg");
   13300   PrintStringProperty("name", name);
   13301   const ZoneList<HBasicBlock*>* blocks = graph->blocks();
   13302   for (int i = 0; i < blocks->length(); i++) {
   13303     HBasicBlock* current = blocks->at(i);
   13304     Tag block_tag(this, "block");
   13305     PrintBlockProperty("name", current->block_id());
   13306     PrintIntProperty("from_bci", -1);
   13307     PrintIntProperty("to_bci", -1);
   13308 
   13309     if (!current->predecessors()->is_empty()) {
   13310       PrintIndent();
   13311       trace_.Add("predecessors");
   13312       for (int j = 0; j < current->predecessors()->length(); ++j) {
   13313         trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
   13314       }
   13315       trace_.Add("\n");
   13316     } else {
   13317       PrintEmptyProperty("predecessors");
   13318     }
   13319 
   13320     if (current->end()->SuccessorCount() == 0) {
   13321       PrintEmptyProperty("successors");
   13322     } else  {
   13323       PrintIndent();
   13324       trace_.Add("successors");
   13325       for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
   13326         trace_.Add(" \"B%d\"", it.Current()->block_id());
   13327       }
   13328       trace_.Add("\n");
   13329     }
   13330 
   13331     PrintEmptyProperty("xhandlers");
   13332 
   13333     {
   13334       PrintIndent();
   13335       trace_.Add("flags");
   13336       if (current->IsLoopSuccessorDominator()) {
   13337         trace_.Add(" \"dom-loop-succ\"");
   13338       }
   13339       if (current->IsUnreachable()) {
   13340         trace_.Add(" \"dead\"");
   13341       }
   13342       if (current->is_osr_entry()) {
   13343         trace_.Add(" \"osr\"");
   13344       }
   13345       trace_.Add("\n");
   13346     }
   13347 
   13348     if (current->dominator() != NULL) {
   13349       PrintBlockProperty("dominator", current->dominator()->block_id());
   13350     }
   13351 
   13352     PrintIntProperty("loop_depth", current->LoopNestingDepth());
   13353 
   13354     if (chunk != NULL) {
   13355       int first_index = current->first_instruction_index();
   13356       int last_index = current->last_instruction_index();
   13357       PrintIntProperty(
   13358           "first_lir_id",
   13359           LifetimePosition::FromInstructionIndex(first_index).Value());
   13360       PrintIntProperty(
   13361           "last_lir_id",
   13362           LifetimePosition::FromInstructionIndex(last_index).Value());
   13363     }
   13364 
   13365     {
   13366       Tag states_tag(this, "states");
   13367       Tag locals_tag(this, "locals");
   13368       int total = current->phis()->length();
   13369       PrintIntProperty("size", current->phis()->length());
   13370       PrintStringProperty("method", "None");
   13371       for (int j = 0; j < total; ++j) {
   13372         HPhi* phi = current->phis()->at(j);
   13373         PrintIndent();
   13374         std::ostringstream os;
   13375         os << phi->merged_index() << " " << NameOf(phi) << " " << *phi << "\n";
   13376         trace_.Add(os.str().c_str());
   13377       }
   13378     }
   13379 
   13380     {
   13381       Tag HIR_tag(this, "HIR");
   13382       for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
   13383         HInstruction* instruction = it.Current();
   13384         int uses = instruction->UseCount();
   13385         PrintIndent();
   13386         std::ostringstream os;
   13387         os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
   13388         if (graph->info()->is_tracking_positions() &&
   13389             instruction->has_position() && instruction->position().raw() != 0) {
   13390           const SourcePosition pos = instruction->position();
   13391           os << " pos:";
   13392           if (pos.inlining_id() != 0) os << pos.inlining_id() << "_";
   13393           os << pos.position();
   13394         }
   13395         os << " <|@\n";
   13396         trace_.Add(os.str().c_str());
   13397       }
   13398     }
   13399 
   13400 
   13401     if (chunk != NULL) {
   13402       Tag LIR_tag(this, "LIR");
   13403       int first_index = current->first_instruction_index();
   13404       int last_index = current->last_instruction_index();
   13405       if (first_index != -1 && last_index != -1) {
   13406         const ZoneList<LInstruction*>* instructions = chunk->instructions();
   13407         for (int i = first_index; i <= last_index; ++i) {
   13408           LInstruction* linstr = instructions->at(i);
   13409           if (linstr != NULL) {
   13410             PrintIndent();
   13411             trace_.Add("%d ",
   13412                        LifetimePosition::FromInstructionIndex(i).Value());
   13413             linstr->PrintTo(&trace_);
   13414             std::ostringstream os;
   13415             os << " [hir:" << NameOf(linstr->hydrogen_value()) << "] <|@\n";
   13416             trace_.Add(os.str().c_str());
   13417           }
   13418         }
   13419       }
   13420     }
   13421   }
   13422 }
   13423 
   13424 
   13425 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
   13426   Tag tag(this, "intervals");
   13427   PrintStringProperty("name", name);
   13428 
   13429   const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
   13430   for (int i = 0; i < fixed_d->length(); ++i) {
   13431     TraceLiveRange(fixed_d->at(i), "fixed", allocator->zone());
   13432   }
   13433 
   13434   const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
   13435   for (int i = 0; i < fixed->length(); ++i) {
   13436     TraceLiveRange(fixed->at(i), "fixed", allocator->zone());
   13437   }
   13438 
   13439   const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
   13440   for (int i = 0; i < live_ranges->length(); ++i) {
   13441     TraceLiveRange(live_ranges->at(i), "object", allocator->zone());
   13442   }
   13443 }
   13444 
   13445 
   13446 void HTracer::TraceLiveRange(LiveRange* range, const char* type,
   13447                              Zone* zone) {
   13448   if (range != NULL && !range->IsEmpty()) {
   13449     PrintIndent();
   13450     trace_.Add("%d %s", range->id(), type);
   13451     if (range->HasRegisterAssigned()) {
   13452       LOperand* op = range->CreateAssignedOperand(zone);
   13453       int assigned_reg = op->index();
   13454       if (op->IsDoubleRegister()) {
   13455         trace_.Add(" \"%s\"",
   13456                    DoubleRegister::from_code(assigned_reg).ToString());
   13457       } else {
   13458         DCHECK(op->IsRegister());
   13459         trace_.Add(" \"%s\"", Register::from_code(assigned_reg).ToString());
   13460       }
   13461     } else if (range->IsSpilled()) {
   13462       LOperand* op = range->TopLevel()->GetSpillOperand();
   13463       if (op->IsDoubleStackSlot()) {
   13464         trace_.Add(" \"double_stack:%d\"", op->index());
   13465       } else {
   13466         DCHECK(op->IsStackSlot());
   13467         trace_.Add(" \"stack:%d\"", op->index());
   13468       }
   13469     }
   13470     int parent_index = -1;
   13471     if (range->IsChild()) {
   13472       parent_index = range->parent()->id();
   13473     } else {
   13474       parent_index = range->id();
   13475     }
   13476     LOperand* op = range->FirstHint();
   13477     int hint_index = -1;
   13478     if (op != NULL && op->IsUnallocated()) {
   13479       hint_index = LUnallocated::cast(op)->virtual_register();
   13480     }
   13481     trace_.Add(" %d %d", parent_index, hint_index);
   13482     UseInterval* cur_interval = range->first_interval();
   13483     while (cur_interval != NULL && range->Covers(cur_interval->start())) {
   13484       trace_.Add(" [%d, %d[",
   13485                  cur_interval->start().Value(),
   13486                  cur_interval->end().Value());
   13487       cur_interval = cur_interval->next();
   13488     }
   13489 
   13490     UsePosition* current_pos = range->first_pos();
   13491     while (current_pos != NULL) {
   13492       if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
   13493         trace_.Add(" %d M", current_pos->pos().Value());
   13494       }
   13495       current_pos = current_pos->next();
   13496     }
   13497 
   13498     trace_.Add(" \"\"\n");
   13499   }
   13500 }
   13501 
   13502 
   13503 void HTracer::FlushToFile() {
   13504   AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
   13505               false);
   13506   trace_.Reset();
   13507 }
   13508 
   13509 
   13510 void HStatistics::Initialize(CompilationInfo* info) {
   13511   if (!info->has_shared_info()) return;
   13512   source_size_ += info->shared_info()->SourceSize();
   13513 }
   13514 
   13515 
   13516 void HStatistics::Print() {
   13517   PrintF(
   13518       "\n"
   13519       "----------------------------------------"
   13520       "----------------------------------------\n"
   13521       "--- Hydrogen timing results:\n"
   13522       "----------------------------------------"
   13523       "----------------------------------------\n");
   13524   base::TimeDelta sum;
   13525   for (int i = 0; i < times_.length(); ++i) {
   13526     sum += times_[i];
   13527   }
   13528 
   13529   for (int i = 0; i < names_.length(); ++i) {
   13530     PrintF("%33s", names_[i]);
   13531     double ms = times_[i].InMillisecondsF();
   13532     double percent = times_[i].PercentOf(sum);
   13533     PrintF(" %8.3f ms / %4.1f %% ", ms, percent);
   13534 
   13535     size_t size = sizes_[i];
   13536     double size_percent = static_cast<double>(size) * 100 / total_size_;
   13537     PrintF(" %9zu bytes / %4.1f %%\n", size, size_percent);
   13538   }
   13539 
   13540   PrintF(
   13541       "----------------------------------------"
   13542       "----------------------------------------\n");
   13543   base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
   13544   PrintF("%33s %8.3f ms / %4.1f %% \n", "Create graph",
   13545          create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
   13546   PrintF("%33s %8.3f ms / %4.1f %% \n", "Optimize graph",
   13547          optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
   13548   PrintF("%33s %8.3f ms / %4.1f %% \n", "Generate and install code",
   13549          generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
   13550   PrintF(
   13551       "----------------------------------------"
   13552       "----------------------------------------\n");
   13553   PrintF("%33s %8.3f ms           %9zu bytes\n", "Total",
   13554          total.InMillisecondsF(), total_size_);
   13555   PrintF("%33s     (%.1f times slower than full code gen)\n", "",
   13556          total.TimesOf(full_code_gen_));
   13557 
   13558   double source_size_in_kb = static_cast<double>(source_size_) / 1024;
   13559   double normalized_time =  source_size_in_kb > 0
   13560       ? total.InMillisecondsF() / source_size_in_kb
   13561       : 0;
   13562   double normalized_size_in_kb =
   13563       source_size_in_kb > 0
   13564           ? static_cast<double>(total_size_) / 1024 / source_size_in_kb
   13565           : 0;
   13566   PrintF("%33s %8.3f ms           %7.3f kB allocated\n",
   13567          "Average per kB source", normalized_time, normalized_size_in_kb);
   13568 }
   13569 
   13570 
   13571 void HStatistics::SaveTiming(const char* name, base::TimeDelta time,
   13572                              size_t size) {
   13573   total_size_ += size;
   13574   for (int i = 0; i < names_.length(); ++i) {
   13575     if (strcmp(names_[i], name) == 0) {
   13576       times_[i] += time;
   13577       sizes_[i] += size;
   13578       return;
   13579     }
   13580   }
   13581   names_.Add(name);
   13582   times_.Add(time);
   13583   sizes_.Add(size);
   13584 }
   13585 
   13586 
   13587 HPhase::~HPhase() {
   13588   if (ShouldProduceTraceOutput()) {
   13589     isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
   13590   }
   13591 
   13592 #ifdef DEBUG
   13593   graph_->Verify(false);  // No full verify.
   13594 #endif
   13595 }
   13596 
   13597 }  // namespace internal
   13598 }  // namespace v8
   13599