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 <memory>
      8 #include <sstream>
      9 
     10 #include "src/allocation-site-scopes.h"
     11 #include "src/ast/ast-numbering.h"
     12 #include "src/ast/compile-time-value.h"
     13 #include "src/ast/scopes.h"
     14 #include "src/code-factory.h"
     15 #include "src/crankshaft/hydrogen-bce.h"
     16 #include "src/crankshaft/hydrogen-canonicalize.h"
     17 #include "src/crankshaft/hydrogen-check-elimination.h"
     18 #include "src/crankshaft/hydrogen-dce.h"
     19 #include "src/crankshaft/hydrogen-dehoist.h"
     20 #include "src/crankshaft/hydrogen-environment-liveness.h"
     21 #include "src/crankshaft/hydrogen-escape-analysis.h"
     22 #include "src/crankshaft/hydrogen-gvn.h"
     23 #include "src/crankshaft/hydrogen-infer-representation.h"
     24 #include "src/crankshaft/hydrogen-infer-types.h"
     25 #include "src/crankshaft/hydrogen-load-elimination.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/field-type.h"
     38 #include "src/full-codegen/full-codegen.h"
     39 #include "src/globals.h"
     40 #include "src/ic/call-optimization.h"
     41 #include "src/ic/ic.h"
     42 // GetRootConstructor
     43 #include "src/ic/ic-inl.h"
     44 #include "src/isolate-inl.h"
     45 #include "src/runtime/runtime.h"
     46 
     47 #if V8_TARGET_ARCH_IA32
     48 #include "src/crankshaft/ia32/lithium-codegen-ia32.h"  // NOLINT
     49 #elif V8_TARGET_ARCH_X64
     50 #include "src/crankshaft/x64/lithium-codegen-x64.h"  // NOLINT
     51 #elif V8_TARGET_ARCH_ARM64
     52 #include "src/crankshaft/arm64/lithium-codegen-arm64.h"  // NOLINT
     53 #elif V8_TARGET_ARCH_ARM
     54 #include "src/crankshaft/arm/lithium-codegen-arm.h"  // NOLINT
     55 #elif V8_TARGET_ARCH_PPC
     56 #include "src/crankshaft/ppc/lithium-codegen-ppc.h"  // NOLINT
     57 #elif V8_TARGET_ARCH_MIPS
     58 #include "src/crankshaft/mips/lithium-codegen-mips.h"  // NOLINT
     59 #elif V8_TARGET_ARCH_MIPS64
     60 #include "src/crankshaft/mips64/lithium-codegen-mips64.h"  // NOLINT
     61 #elif V8_TARGET_ARCH_S390
     62 #include "src/crankshaft/s390/lithium-codegen-s390.h"  // NOLINT
     63 #elif V8_TARGET_ARCH_X87
     64 #include "src/crankshaft/x87/lithium-codegen-x87.h"  // NOLINT
     65 #else
     66 #error Unsupported target architecture.
     67 #endif
     68 
     69 namespace v8 {
     70 namespace internal {
     71 
     72 const auto GetRegConfig = RegisterConfiguration::Crankshaft;
     73 
     74 class HOptimizedGraphBuilderWithPositions : public HOptimizedGraphBuilder {
     75  public:
     76   explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info)
     77       : HOptimizedGraphBuilder(info, true) {
     78     SetSourcePosition(info->shared_info()->start_position());
     79   }
     80 
     81 #define DEF_VISIT(type)                                      \
     82   void Visit##type(type* node) override {                    \
     83     SourcePosition old_position = SourcePosition::Unknown(); \
     84     if (node->position() != kNoSourcePosition) {             \
     85       old_position = source_position();                      \
     86       SetSourcePosition(node->position());                   \
     87     }                                                        \
     88     HOptimizedGraphBuilder::Visit##type(node);               \
     89     if (old_position.IsKnown()) {                            \
     90       set_source_position(old_position);                     \
     91     }                                                        \
     92   }
     93   EXPRESSION_NODE_LIST(DEF_VISIT)
     94 #undef DEF_VISIT
     95 
     96 #define DEF_VISIT(type)                                      \
     97   void Visit##type(type* node) override {                    \
     98     SourcePosition old_position = SourcePosition::Unknown(); \
     99     if (node->position() != kNoSourcePosition) {             \
    100       old_position = source_position();                      \
    101       SetSourcePosition(node->position());                   \
    102     }                                                        \
    103     HOptimizedGraphBuilder::Visit##type(node);               \
    104     if (old_position.IsKnown()) {                            \
    105       set_source_position(old_position);                     \
    106     }                                                        \
    107   }
    108   STATEMENT_NODE_LIST(DEF_VISIT)
    109 #undef DEF_VISIT
    110 
    111 #define DEF_VISIT(type)                        \
    112   void Visit##type(type* node) override {      \
    113     HOptimizedGraphBuilder::Visit##type(node); \
    114   }
    115   DECLARATION_NODE_LIST(DEF_VISIT)
    116 #undef DEF_VISIT
    117 };
    118 
    119 HCompilationJob::Status HCompilationJob::PrepareJobImpl() {
    120   if (!isolate()->use_crankshaft() ||
    121       info()->shared_info()->dont_crankshaft()) {
    122     // Crankshaft is entirely disabled.
    123     return FAILED;
    124   }
    125 
    126   // Optimization requires a version of fullcode with deoptimization support.
    127   // Recompile the unoptimized version of the code if the current version
    128   // doesn't have deoptimization support already.
    129   // Otherwise, if we are gathering compilation time and space statistics
    130   // for hydrogen, gather baseline statistics for a fullcode compilation.
    131   bool should_recompile = !info()->shared_info()->has_deoptimization_support();
    132   if (should_recompile || FLAG_hydrogen_stats) {
    133     base::ElapsedTimer timer;
    134     if (FLAG_hydrogen_stats) {
    135       timer.Start();
    136     }
    137     if (!Compiler::EnsureDeoptimizationSupport(info())) {
    138       return FAILED;
    139     }
    140     if (FLAG_hydrogen_stats) {
    141       isolate()->GetHStatistics()->IncrementFullCodeGen(timer.Elapsed());
    142     }
    143   }
    144   DCHECK(info()->shared_info()->has_deoptimization_support());
    145   DCHECK(!info()->shared_info()->never_compiled());
    146 
    147   // Check the whitelist for Crankshaft.
    148   if (!info()->shared_info()->PassesFilter(FLAG_hydrogen_filter)) {
    149     return AbortOptimization(kHydrogenFilter);
    150   }
    151 
    152   Scope* scope = info()->scope();
    153   if (LUnallocated::TooManyParameters(scope->num_parameters())) {
    154     // Crankshaft would require too many Lithium operands.
    155     return AbortOptimization(kTooManyParameters);
    156   }
    157 
    158   if (info()->is_osr() &&
    159       LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(),
    160                                                   scope->num_stack_slots())) {
    161     // Crankshaft would require too many Lithium operands.
    162     return AbortOptimization(kTooManyParametersLocals);
    163   }
    164 
    165   if (IsGeneratorFunction(info()->shared_info()->kind())) {
    166     // Crankshaft does not support generators.
    167     return AbortOptimization(kGenerator);
    168   }
    169 
    170   if (FLAG_trace_hydrogen) {
    171     isolate()->GetHTracer()->TraceCompilation(info());
    172   }
    173 
    174   // Optimization could have been disabled by the parser. Note that this check
    175   // is only needed because the Hydrogen graph builder is missing some bailouts.
    176   if (info()->shared_info()->optimization_disabled()) {
    177     return AbortOptimization(
    178         info()->shared_info()->disable_optimization_reason());
    179   }
    180 
    181   HOptimizedGraphBuilder* graph_builder =
    182       (FLAG_hydrogen_track_positions || isolate()->is_profiling() ||
    183        FLAG_trace_ic)
    184           ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info())
    185           : new (info()->zone()) HOptimizedGraphBuilder(info(), false);
    186 
    187   // Type-check the function.
    188   AstTyper(info()->isolate(), info()->zone(), info()->closure(),
    189            info()->scope(), info()->osr_ast_id(), info()->literal(),
    190            graph_builder->bounds())
    191       .Run();
    192 
    193   graph_ = graph_builder->CreateGraph();
    194 
    195   if (isolate()->has_pending_exception()) {
    196     return FAILED;
    197   }
    198 
    199   if (graph_ == NULL) return FAILED;
    200 
    201   if (info()->dependencies()->HasAborted()) {
    202     // Dependency has changed during graph creation. Let's try again later.
    203     return RetryOptimization(kBailedOutDueToDependencyChange);
    204   }
    205 
    206   return SUCCEEDED;
    207 }
    208 
    209 HCompilationJob::Status HCompilationJob::ExecuteJobImpl() {
    210   DCHECK(graph_ != NULL);
    211   BailoutReason bailout_reason = kNoReason;
    212 
    213   if (graph_->Optimize(&bailout_reason)) {
    214     chunk_ = LChunk::NewChunk(graph_);
    215     if (chunk_ != NULL) return SUCCEEDED;
    216   } else if (bailout_reason != kNoReason) {
    217     info()->AbortOptimization(bailout_reason);
    218   }
    219 
    220   return FAILED;
    221 }
    222 
    223 HCompilationJob::Status HCompilationJob::FinalizeJobImpl() {
    224   DCHECK(chunk_ != NULL);
    225   DCHECK(graph_ != NULL);
    226   {
    227     // Deferred handles reference objects that were accessible during
    228     // graph creation.  To make sure that we don't encounter inconsistencies
    229     // between graph creation and code generation, we disallow accessing
    230     // objects through deferred handles during the latter, with exceptions.
    231     DisallowDeferredHandleDereference no_deferred_handle_deref;
    232     Handle<Code> optimized_code = chunk_->Codegen();
    233     if (optimized_code.is_null()) {
    234       if (info()->bailout_reason() == kNoReason) {
    235         return AbortOptimization(kCodeGenerationFailed);
    236       }
    237       return FAILED;
    238     }
    239     RegisterWeakObjectsInOptimizedCode(optimized_code);
    240     info()->SetCode(optimized_code);
    241   }
    242   // Add to the weak list of optimized code objects.
    243   info()->context()->native_context()->AddOptimizedCode(*info()->code());
    244   return SUCCEEDED;
    245 }
    246 
    247 HBasicBlock::HBasicBlock(HGraph* graph)
    248     : block_id_(graph->GetNextBlockID()),
    249       graph_(graph),
    250       phis_(4, graph->zone()),
    251       first_(NULL),
    252       last_(NULL),
    253       end_(NULL),
    254       loop_information_(NULL),
    255       predecessors_(2, graph->zone()),
    256       dominator_(NULL),
    257       dominated_blocks_(4, graph->zone()),
    258       last_environment_(NULL),
    259       argument_count_(-1),
    260       first_instruction_index_(-1),
    261       last_instruction_index_(-1),
    262       deleted_phis_(4, graph->zone()),
    263       parent_loop_header_(NULL),
    264       inlined_entry_block_(NULL),
    265       is_inline_return_target_(false),
    266       is_reachable_(true),
    267       dominates_loop_successors_(false),
    268       is_osr_entry_(false),
    269       is_ordered_(false) { }
    270 
    271 
    272 Isolate* HBasicBlock::isolate() const {
    273   return graph_->isolate();
    274 }
    275 
    276 
    277 void HBasicBlock::MarkUnreachable() {
    278   is_reachable_ = false;
    279 }
    280 
    281 
    282 void HBasicBlock::AttachLoopInformation() {
    283   DCHECK(!IsLoopHeader());
    284   loop_information_ = new(zone()) HLoopInformation(this, zone());
    285 }
    286 
    287 
    288 void HBasicBlock::DetachLoopInformation() {
    289   DCHECK(IsLoopHeader());
    290   loop_information_ = NULL;
    291 }
    292 
    293 
    294 void HBasicBlock::AddPhi(HPhi* phi) {
    295   DCHECK(!IsStartBlock());
    296   phis_.Add(phi, zone());
    297   phi->SetBlock(this);
    298 }
    299 
    300 
    301 void HBasicBlock::RemovePhi(HPhi* phi) {
    302   DCHECK(phi->block() == this);
    303   DCHECK(phis_.Contains(phi));
    304   phi->Kill();
    305   phis_.RemoveElement(phi);
    306   phi->SetBlock(NULL);
    307 }
    308 
    309 
    310 void HBasicBlock::AddInstruction(HInstruction* instr, SourcePosition position) {
    311   DCHECK(!IsStartBlock() || !IsFinished());
    312   DCHECK(!instr->IsLinked());
    313   DCHECK(!IsFinished());
    314 
    315   if (position.IsKnown()) {
    316     instr->set_position(position);
    317   }
    318   if (first_ == NULL) {
    319     DCHECK(last_environment() != NULL);
    320     DCHECK(!last_environment()->ast_id().IsNone());
    321     HBlockEntry* entry = new(zone()) HBlockEntry();
    322     entry->InitializeAsFirst(this);
    323     if (position.IsKnown()) {
    324       entry->set_position(position);
    325     } else {
    326       DCHECK(!FLAG_hydrogen_track_positions ||
    327              !graph()->info()->IsOptimizing() || instr->IsAbnormalExit());
    328     }
    329     first_ = last_ = entry;
    330   }
    331   instr->InsertAfter(last_);
    332 }
    333 
    334 
    335 HPhi* HBasicBlock::AddNewPhi(int merged_index) {
    336   if (graph()->IsInsideNoSideEffectsScope()) {
    337     merged_index = HPhi::kInvalidMergedIndex;
    338   }
    339   HPhi* phi = new(zone()) HPhi(merged_index, zone());
    340   AddPhi(phi);
    341   return phi;
    342 }
    343 
    344 
    345 HSimulate* HBasicBlock::CreateSimulate(BailoutId ast_id,
    346                                        RemovableSimulate removable) {
    347   DCHECK(HasEnvironment());
    348   HEnvironment* environment = last_environment();
    349   DCHECK(ast_id.IsNone() ||
    350          ast_id == BailoutId::StubEntry() ||
    351          environment->closure()->shared()->VerifyBailoutId(ast_id));
    352 
    353   int push_count = environment->push_count();
    354   int pop_count = environment->pop_count();
    355 
    356   HSimulate* instr =
    357       new(zone()) HSimulate(ast_id, pop_count, zone(), removable);
    358 #ifdef DEBUG
    359   instr->set_closure(environment->closure());
    360 #endif
    361   // Order of pushed values: newest (top of stack) first. This allows
    362   // HSimulate::MergeWith() to easily append additional pushed values
    363   // that are older (from further down the stack).
    364   for (int i = 0; i < push_count; ++i) {
    365     instr->AddPushedValue(environment->ExpressionStackAt(i));
    366   }
    367   for (GrowableBitVector::Iterator it(environment->assigned_variables(),
    368                                       zone());
    369        !it.Done();
    370        it.Advance()) {
    371     int index = it.Current();
    372     instr->AddAssignedValue(index, environment->Lookup(index));
    373   }
    374   environment->ClearHistory();
    375   return instr;
    376 }
    377 
    378 
    379 void HBasicBlock::Finish(HControlInstruction* end, SourcePosition position) {
    380   DCHECK(!IsFinished());
    381   AddInstruction(end, position);
    382   end_ = end;
    383   for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    384     it.Current()->RegisterPredecessor(this);
    385   }
    386 }
    387 
    388 
    389 void HBasicBlock::Goto(HBasicBlock* block, SourcePosition position,
    390                        FunctionState* state, bool add_simulate) {
    391   bool drop_extra = state != NULL &&
    392       state->inlining_kind() == NORMAL_RETURN;
    393 
    394   if (block->IsInlineReturnTarget()) {
    395     HEnvironment* env = last_environment();
    396     int argument_count = env->arguments_environment()->parameter_count();
    397     AddInstruction(new(zone())
    398                    HLeaveInlined(state->entry(), argument_count),
    399                    position);
    400     UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
    401   }
    402 
    403   if (add_simulate) AddNewSimulate(BailoutId::None(), position);
    404   HGoto* instr = new(zone()) HGoto(block);
    405   Finish(instr, position);
    406 }
    407 
    408 
    409 void HBasicBlock::AddLeaveInlined(HValue* return_value, FunctionState* state,
    410                                   SourcePosition position) {
    411   HBasicBlock* target = state->function_return();
    412   bool drop_extra = state->inlining_kind() == NORMAL_RETURN;
    413 
    414   DCHECK(target->IsInlineReturnTarget());
    415   DCHECK(return_value != NULL);
    416   HEnvironment* env = last_environment();
    417   int argument_count = env->arguments_environment()->parameter_count();
    418   AddInstruction(new(zone()) HLeaveInlined(state->entry(), argument_count),
    419                  position);
    420   UpdateEnvironment(last_environment()->DiscardInlined(drop_extra));
    421   last_environment()->Push(return_value);
    422   AddNewSimulate(BailoutId::None(), position);
    423   HGoto* instr = new(zone()) HGoto(target);
    424   Finish(instr, position);
    425 }
    426 
    427 
    428 void HBasicBlock::SetInitialEnvironment(HEnvironment* env) {
    429   DCHECK(!HasEnvironment());
    430   DCHECK(first() == NULL);
    431   UpdateEnvironment(env);
    432 }
    433 
    434 
    435 void HBasicBlock::UpdateEnvironment(HEnvironment* env) {
    436   last_environment_ = env;
    437   graph()->update_maximum_environment_size(env->first_expression_index());
    438 }
    439 
    440 
    441 void HBasicBlock::SetJoinId(BailoutId ast_id) {
    442   int length = predecessors_.length();
    443   DCHECK(length > 0);
    444   for (int i = 0; i < length; i++) {
    445     HBasicBlock* predecessor = predecessors_[i];
    446     DCHECK(predecessor->end()->IsGoto());
    447     HSimulate* simulate = HSimulate::cast(predecessor->end()->previous());
    448     DCHECK(i != 0 ||
    449            (predecessor->last_environment()->closure().is_null() ||
    450             predecessor->last_environment()->closure()->shared()
    451               ->VerifyBailoutId(ast_id)));
    452     simulate->set_ast_id(ast_id);
    453     predecessor->last_environment()->set_ast_id(ast_id);
    454   }
    455 }
    456 
    457 
    458 bool HBasicBlock::Dominates(HBasicBlock* other) const {
    459   HBasicBlock* current = other->dominator();
    460   while (current != NULL) {
    461     if (current == this) return true;
    462     current = current->dominator();
    463   }
    464   return false;
    465 }
    466 
    467 
    468 bool HBasicBlock::EqualToOrDominates(HBasicBlock* other) const {
    469   if (this == other) return true;
    470   return Dominates(other);
    471 }
    472 
    473 
    474 int HBasicBlock::LoopNestingDepth() const {
    475   const HBasicBlock* current = this;
    476   int result  = (current->IsLoopHeader()) ? 1 : 0;
    477   while (current->parent_loop_header() != NULL) {
    478     current = current->parent_loop_header();
    479     result++;
    480   }
    481   return result;
    482 }
    483 
    484 
    485 void HBasicBlock::PostProcessLoopHeader(IterationStatement* stmt) {
    486   DCHECK(IsLoopHeader());
    487 
    488   SetJoinId(stmt->EntryId());
    489   if (predecessors()->length() == 1) {
    490     // This is a degenerated loop.
    491     DetachLoopInformation();
    492     return;
    493   }
    494 
    495   // Only the first entry into the loop is from outside the loop. All other
    496   // entries must be back edges.
    497   for (int i = 1; i < predecessors()->length(); ++i) {
    498     loop_information()->RegisterBackEdge(predecessors()->at(i));
    499   }
    500 }
    501 
    502 
    503 void HBasicBlock::MarkSuccEdgeUnreachable(int succ) {
    504   DCHECK(IsFinished());
    505   HBasicBlock* succ_block = end()->SuccessorAt(succ);
    506 
    507   DCHECK(succ_block->predecessors()->length() == 1);
    508   succ_block->MarkUnreachable();
    509 }
    510 
    511 
    512 void HBasicBlock::RegisterPredecessor(HBasicBlock* pred) {
    513   if (HasPredecessor()) {
    514     // Only loop header blocks can have a predecessor added after
    515     // instructions have been added to the block (they have phis for all
    516     // values in the environment, these phis may be eliminated later).
    517     DCHECK(IsLoopHeader() || first_ == NULL);
    518     HEnvironment* incoming_env = pred->last_environment();
    519     if (IsLoopHeader()) {
    520       DCHECK_EQ(phis()->length(), incoming_env->length());
    521       for (int i = 0; i < phis_.length(); ++i) {
    522         phis_[i]->AddInput(incoming_env->values()->at(i));
    523       }
    524     } else {
    525       last_environment()->AddIncomingEdge(this, pred->last_environment());
    526     }
    527   } else if (!HasEnvironment() && !IsFinished()) {
    528     DCHECK(!IsLoopHeader());
    529     SetInitialEnvironment(pred->last_environment()->Copy());
    530   }
    531 
    532   predecessors_.Add(pred, zone());
    533 }
    534 
    535 
    536 void HBasicBlock::AddDominatedBlock(HBasicBlock* block) {
    537   DCHECK(!dominated_blocks_.Contains(block));
    538   // Keep the list of dominated blocks sorted such that if there is two
    539   // succeeding block in this list, the predecessor is before the successor.
    540   int index = 0;
    541   while (index < dominated_blocks_.length() &&
    542          dominated_blocks_[index]->block_id() < block->block_id()) {
    543     ++index;
    544   }
    545   dominated_blocks_.InsertAt(index, block, zone());
    546 }
    547 
    548 
    549 void HBasicBlock::AssignCommonDominator(HBasicBlock* other) {
    550   if (dominator_ == NULL) {
    551     dominator_ = other;
    552     other->AddDominatedBlock(this);
    553   } else if (other->dominator() != NULL) {
    554     HBasicBlock* first = dominator_;
    555     HBasicBlock* second = other;
    556 
    557     while (first != second) {
    558       if (first->block_id() > second->block_id()) {
    559         first = first->dominator();
    560       } else {
    561         second = second->dominator();
    562       }
    563       DCHECK(first != NULL && second != NULL);
    564     }
    565 
    566     if (dominator_ != first) {
    567       DCHECK(dominator_->dominated_blocks_.Contains(this));
    568       dominator_->dominated_blocks_.RemoveElement(this);
    569       dominator_ = first;
    570       first->AddDominatedBlock(this);
    571     }
    572   }
    573 }
    574 
    575 
    576 void HBasicBlock::AssignLoopSuccessorDominators() {
    577   // Mark blocks that dominate all subsequent reachable blocks inside their
    578   // loop. Exploit the fact that blocks are sorted in reverse post order. When
    579   // the loop is visited in increasing block id order, if the number of
    580   // non-loop-exiting successor edges at the dominator_candidate block doesn't
    581   // exceed the number of previously encountered predecessor edges, there is no
    582   // path from the loop header to any block with higher id that doesn't go
    583   // through the dominator_candidate block. In this case, the
    584   // dominator_candidate block is guaranteed to dominate all blocks reachable
    585   // from it with higher ids.
    586   HBasicBlock* last = loop_information()->GetLastBackEdge();
    587   int outstanding_successors = 1;  // one edge from the pre-header
    588   // Header always dominates everything.
    589   MarkAsLoopSuccessorDominator();
    590   for (int j = block_id(); j <= last->block_id(); ++j) {
    591     HBasicBlock* dominator_candidate = graph_->blocks()->at(j);
    592     for (HPredecessorIterator it(dominator_candidate); !it.Done();
    593          it.Advance()) {
    594       HBasicBlock* predecessor = it.Current();
    595       // Don't count back edges.
    596       if (predecessor->block_id() < dominator_candidate->block_id()) {
    597         outstanding_successors--;
    598       }
    599     }
    600 
    601     // If more successors than predecessors have been seen in the loop up to
    602     // now, it's not possible to guarantee that the current block dominates
    603     // all of the blocks with higher IDs. In this case, assume conservatively
    604     // that those paths through loop that don't go through the current block
    605     // contain all of the loop's dependencies. Also be careful to record
    606     // dominator information about the current loop that's being processed,
    607     // and not nested loops, which will be processed when
    608     // AssignLoopSuccessorDominators gets called on their header.
    609     DCHECK(outstanding_successors >= 0);
    610     HBasicBlock* parent_loop_header = dominator_candidate->parent_loop_header();
    611     if (outstanding_successors == 0 &&
    612         (parent_loop_header == this && !dominator_candidate->IsLoopHeader())) {
    613       dominator_candidate->MarkAsLoopSuccessorDominator();
    614     }
    615     HControlInstruction* end = dominator_candidate->end();
    616     for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    617       HBasicBlock* successor = it.Current();
    618       // Only count successors that remain inside the loop and don't loop back
    619       // to a loop header.
    620       if (successor->block_id() > dominator_candidate->block_id() &&
    621           successor->block_id() <= last->block_id()) {
    622         // Backwards edges must land on loop headers.
    623         DCHECK(successor->block_id() > dominator_candidate->block_id() ||
    624                successor->IsLoopHeader());
    625         outstanding_successors++;
    626       }
    627     }
    628   }
    629 }
    630 
    631 
    632 int HBasicBlock::PredecessorIndexOf(HBasicBlock* predecessor) const {
    633   for (int i = 0; i < predecessors_.length(); ++i) {
    634     if (predecessors_[i] == predecessor) return i;
    635   }
    636   UNREACHABLE();
    637   return -1;
    638 }
    639 
    640 
    641 #ifdef DEBUG
    642 void HBasicBlock::Verify() {
    643   // Check that every block is finished.
    644   DCHECK(IsFinished());
    645   DCHECK(block_id() >= 0);
    646 
    647   // Check that the incoming edges are in edge split form.
    648   if (predecessors_.length() > 1) {
    649     for (int i = 0; i < predecessors_.length(); ++i) {
    650       DCHECK(predecessors_[i]->end()->SecondSuccessor() == NULL);
    651     }
    652   }
    653 }
    654 #endif
    655 
    656 
    657 void HLoopInformation::RegisterBackEdge(HBasicBlock* block) {
    658   this->back_edges_.Add(block, block->zone());
    659   AddBlock(block);
    660 }
    661 
    662 
    663 HBasicBlock* HLoopInformation::GetLastBackEdge() const {
    664   int max_id = -1;
    665   HBasicBlock* result = NULL;
    666   for (int i = 0; i < back_edges_.length(); ++i) {
    667     HBasicBlock* cur = back_edges_[i];
    668     if (cur->block_id() > max_id) {
    669       max_id = cur->block_id();
    670       result = cur;
    671     }
    672   }
    673   return result;
    674 }
    675 
    676 
    677 void HLoopInformation::AddBlock(HBasicBlock* block) {
    678   if (block == loop_header()) return;
    679   if (block->parent_loop_header() == loop_header()) return;
    680   if (block->parent_loop_header() != NULL) {
    681     AddBlock(block->parent_loop_header());
    682   } else {
    683     block->set_parent_loop_header(loop_header());
    684     blocks_.Add(block, block->zone());
    685     for (int i = 0; i < block->predecessors()->length(); ++i) {
    686       AddBlock(block->predecessors()->at(i));
    687     }
    688   }
    689 }
    690 
    691 
    692 #ifdef DEBUG
    693 
    694 // Checks reachability of the blocks in this graph and stores a bit in
    695 // the BitVector "reachable()" for every block that can be reached
    696 // from the start block of the graph. If "dont_visit" is non-null, the given
    697 // block is treated as if it would not be part of the graph. "visited_count()"
    698 // returns the number of reachable blocks.
    699 class ReachabilityAnalyzer BASE_EMBEDDED {
    700  public:
    701   ReachabilityAnalyzer(HBasicBlock* entry_block,
    702                        int block_count,
    703                        HBasicBlock* dont_visit)
    704       : visited_count_(0),
    705         stack_(16, entry_block->zone()),
    706         reachable_(block_count, entry_block->zone()),
    707         dont_visit_(dont_visit) {
    708     PushBlock(entry_block);
    709     Analyze();
    710   }
    711 
    712   int visited_count() const { return visited_count_; }
    713   const BitVector* reachable() const { return &reachable_; }
    714 
    715  private:
    716   void PushBlock(HBasicBlock* block) {
    717     if (block != NULL && block != dont_visit_ &&
    718         !reachable_.Contains(block->block_id())) {
    719       reachable_.Add(block->block_id());
    720       stack_.Add(block, block->zone());
    721       visited_count_++;
    722     }
    723   }
    724 
    725   void Analyze() {
    726     while (!stack_.is_empty()) {
    727       HControlInstruction* end = stack_.RemoveLast()->end();
    728       for (HSuccessorIterator it(end); !it.Done(); it.Advance()) {
    729         PushBlock(it.Current());
    730       }
    731     }
    732   }
    733 
    734   int visited_count_;
    735   ZoneList<HBasicBlock*> stack_;
    736   BitVector reachable_;
    737   HBasicBlock* dont_visit_;
    738 };
    739 
    740 
    741 void HGraph::Verify(bool do_full_verify) const {
    742   Heap::RelocationLock relocation_lock(isolate()->heap());
    743   AllowHandleDereference allow_deref;
    744   AllowDeferredHandleDereference allow_deferred_deref;
    745   for (int i = 0; i < blocks_.length(); i++) {
    746     HBasicBlock* block = blocks_.at(i);
    747 
    748     block->Verify();
    749 
    750     // Check that every block contains at least one node and that only the last
    751     // node is a control instruction.
    752     HInstruction* current = block->first();
    753     DCHECK(current != NULL && current->IsBlockEntry());
    754     while (current != NULL) {
    755       DCHECK((current->next() == NULL) == current->IsControlInstruction());
    756       DCHECK(current->block() == block);
    757       current->Verify();
    758       current = current->next();
    759     }
    760 
    761     // Check that successors are correctly set.
    762     HBasicBlock* first = block->end()->FirstSuccessor();
    763     HBasicBlock* second = block->end()->SecondSuccessor();
    764     DCHECK(second == NULL || first != NULL);
    765 
    766     // Check that the predecessor array is correct.
    767     if (first != NULL) {
    768       DCHECK(first->predecessors()->Contains(block));
    769       if (second != NULL) {
    770         DCHECK(second->predecessors()->Contains(block));
    771       }
    772     }
    773 
    774     // Check that phis have correct arguments.
    775     for (int j = 0; j < block->phis()->length(); j++) {
    776       HPhi* phi = block->phis()->at(j);
    777       phi->Verify();
    778     }
    779 
    780     // Check that all join blocks have predecessors that end with an
    781     // unconditional goto and agree on their environment node id.
    782     if (block->predecessors()->length() >= 2) {
    783       BailoutId id =
    784           block->predecessors()->first()->last_environment()->ast_id();
    785       for (int k = 0; k < block->predecessors()->length(); k++) {
    786         HBasicBlock* predecessor = block->predecessors()->at(k);
    787         DCHECK(predecessor->end()->IsGoto() ||
    788                predecessor->end()->IsDeoptimize());
    789         DCHECK(predecessor->last_environment()->ast_id() == id);
    790       }
    791     }
    792   }
    793 
    794   // Check special property of first block to have no predecessors.
    795   DCHECK(blocks_.at(0)->predecessors()->is_empty());
    796 
    797   if (do_full_verify) {
    798     // Check that the graph is fully connected.
    799     ReachabilityAnalyzer analyzer(entry_block_, blocks_.length(), NULL);
    800     DCHECK(analyzer.visited_count() == blocks_.length());
    801 
    802     // Check that entry block dominator is NULL.
    803     DCHECK(entry_block_->dominator() == NULL);
    804 
    805     // Check dominators.
    806     for (int i = 0; i < blocks_.length(); ++i) {
    807       HBasicBlock* block = blocks_.at(i);
    808       if (block->dominator() == NULL) {
    809         // Only start block may have no dominator assigned to.
    810         DCHECK(i == 0);
    811       } else {
    812         // Assert that block is unreachable if dominator must not be visited.
    813         ReachabilityAnalyzer dominator_analyzer(entry_block_,
    814                                                 blocks_.length(),
    815                                                 block->dominator());
    816         DCHECK(!dominator_analyzer.reachable()->Contains(block->block_id()));
    817       }
    818     }
    819   }
    820 }
    821 
    822 #endif
    823 
    824 
    825 HConstant* HGraph::GetConstant(SetOncePointer<HConstant>* pointer,
    826                                int32_t value) {
    827   if (!pointer->is_set()) {
    828     // Can't pass GetInvalidContext() to HConstant::New, because that will
    829     // recursively call GetConstant
    830     HConstant* constant = HConstant::New(isolate(), zone(), NULL, value);
    831     constant->InsertAfter(entry_block()->first());
    832     pointer->set(constant);
    833     return constant;
    834   }
    835   return ReinsertConstantIfNecessary(pointer->get());
    836 }
    837 
    838 
    839 HConstant* HGraph::ReinsertConstantIfNecessary(HConstant* constant) {
    840   if (!constant->IsLinked()) {
    841     // The constant was removed from the graph. Reinsert.
    842     constant->ClearFlag(HValue::kIsDead);
    843     constant->InsertAfter(entry_block()->first());
    844   }
    845   return constant;
    846 }
    847 
    848 
    849 HConstant* HGraph::GetConstant0() {
    850   return GetConstant(&constant_0_, 0);
    851 }
    852 
    853 
    854 HConstant* HGraph::GetConstant1() {
    855   return GetConstant(&constant_1_, 1);
    856 }
    857 
    858 
    859 HConstant* HGraph::GetConstantMinus1() {
    860   return GetConstant(&constant_minus1_, -1);
    861 }
    862 
    863 
    864 HConstant* HGraph::GetConstantBool(bool value) {
    865   return value ? GetConstantTrue() : GetConstantFalse();
    866 }
    867 
    868 #define DEFINE_GET_CONSTANT(Name, name, constant, type, htype, boolean_value, \
    869                             undetectable)                                     \
    870   HConstant* HGraph::GetConstant##Name() {                                    \
    871     if (!constant_##name##_.is_set()) {                                       \
    872       HConstant* constant = new (zone()) HConstant(                           \
    873           Unique<Object>::CreateImmovable(isolate()->factory()->constant()),  \
    874           Unique<Map>::CreateImmovable(isolate()->factory()->type##_map()),   \
    875           false, Representation::Tagged(), htype, true, boolean_value,        \
    876           undetectable, ODDBALL_TYPE);                                        \
    877       constant->InsertAfter(entry_block()->first());                          \
    878       constant_##name##_.set(constant);                                       \
    879     }                                                                         \
    880     return ReinsertConstantIfNecessary(constant_##name##_.get());             \
    881   }
    882 
    883 DEFINE_GET_CONSTANT(Undefined, undefined, undefined_value, undefined,
    884                     HType::Undefined(), false, true)
    885 DEFINE_GET_CONSTANT(True, true, true_value, boolean, HType::Boolean(), true,
    886                     false)
    887 DEFINE_GET_CONSTANT(False, false, false_value, boolean, HType::Boolean(), false,
    888                     false)
    889 DEFINE_GET_CONSTANT(Hole, the_hole, the_hole_value, the_hole, HType::None(),
    890                     false, false)
    891 DEFINE_GET_CONSTANT(Null, null, null_value, null, HType::Null(), false, true)
    892 DEFINE_GET_CONSTANT(OptimizedOut, optimized_out, optimized_out, optimized_out,
    893                     HType::None(), false, false)
    894 
    895 #undef DEFINE_GET_CONSTANT
    896 
    897 #define DEFINE_IS_CONSTANT(Name, name)                                         \
    898 bool HGraph::IsConstant##Name(HConstant* constant) {                           \
    899   return constant_##name##_.is_set() && constant == constant_##name##_.get();  \
    900 }
    901 DEFINE_IS_CONSTANT(Undefined, undefined)
    902 DEFINE_IS_CONSTANT(0, 0)
    903 DEFINE_IS_CONSTANT(1, 1)
    904 DEFINE_IS_CONSTANT(Minus1, minus1)
    905 DEFINE_IS_CONSTANT(True, true)
    906 DEFINE_IS_CONSTANT(False, false)
    907 DEFINE_IS_CONSTANT(Hole, the_hole)
    908 DEFINE_IS_CONSTANT(Null, null)
    909 
    910 #undef DEFINE_IS_CONSTANT
    911 
    912 
    913 HConstant* HGraph::GetInvalidContext() {
    914   return GetConstant(&constant_invalid_context_, 0xFFFFC0C7);
    915 }
    916 
    917 
    918 bool HGraph::IsStandardConstant(HConstant* constant) {
    919   if (IsConstantUndefined(constant)) return true;
    920   if (IsConstant0(constant)) return true;
    921   if (IsConstant1(constant)) return true;
    922   if (IsConstantMinus1(constant)) return true;
    923   if (IsConstantTrue(constant)) return true;
    924   if (IsConstantFalse(constant)) return true;
    925   if (IsConstantHole(constant)) return true;
    926   if (IsConstantNull(constant)) return true;
    927   return false;
    928 }
    929 
    930 
    931 HGraphBuilder::IfBuilder::IfBuilder() : builder_(NULL), needs_compare_(true) {}
    932 
    933 
    934 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder)
    935     : needs_compare_(true) {
    936   Initialize(builder);
    937 }
    938 
    939 
    940 HGraphBuilder::IfBuilder::IfBuilder(HGraphBuilder* builder,
    941                                     HIfContinuation* continuation)
    942     : needs_compare_(false), first_true_block_(NULL), first_false_block_(NULL) {
    943   InitializeDontCreateBlocks(builder);
    944   continuation->Continue(&first_true_block_, &first_false_block_);
    945 }
    946 
    947 
    948 void HGraphBuilder::IfBuilder::InitializeDontCreateBlocks(
    949     HGraphBuilder* builder) {
    950   builder_ = builder;
    951   finished_ = false;
    952   did_then_ = false;
    953   did_else_ = false;
    954   did_else_if_ = false;
    955   did_and_ = false;
    956   did_or_ = false;
    957   captured_ = false;
    958   pending_merge_block_ = false;
    959   split_edge_merge_block_ = NULL;
    960   merge_at_join_blocks_ = NULL;
    961   normal_merge_at_join_block_count_ = 0;
    962   deopt_merge_at_join_block_count_ = 0;
    963 }
    964 
    965 
    966 void HGraphBuilder::IfBuilder::Initialize(HGraphBuilder* builder) {
    967   InitializeDontCreateBlocks(builder);
    968   HEnvironment* env = builder->environment();
    969   first_true_block_ = builder->CreateBasicBlock(env->Copy());
    970   first_false_block_ = builder->CreateBasicBlock(env->Copy());
    971 }
    972 
    973 
    974 HControlInstruction* HGraphBuilder::IfBuilder::AddCompare(
    975     HControlInstruction* compare) {
    976   DCHECK(did_then_ == did_else_);
    977   if (did_else_) {
    978     // Handle if-then-elseif
    979     did_else_if_ = true;
    980     did_else_ = false;
    981     did_then_ = false;
    982     did_and_ = false;
    983     did_or_ = false;
    984     pending_merge_block_ = false;
    985     split_edge_merge_block_ = NULL;
    986     HEnvironment* env = builder()->environment();
    987     first_true_block_ = builder()->CreateBasicBlock(env->Copy());
    988     first_false_block_ = builder()->CreateBasicBlock(env->Copy());
    989   }
    990   if (split_edge_merge_block_ != NULL) {
    991     HEnvironment* env = first_false_block_->last_environment();
    992     HBasicBlock* split_edge = builder()->CreateBasicBlock(env->Copy());
    993     if (did_or_) {
    994       compare->SetSuccessorAt(0, split_edge);
    995       compare->SetSuccessorAt(1, first_false_block_);
    996     } else {
    997       compare->SetSuccessorAt(0, first_true_block_);
    998       compare->SetSuccessorAt(1, split_edge);
    999     }
   1000     builder()->GotoNoSimulate(split_edge, split_edge_merge_block_);
   1001   } else {
   1002     compare->SetSuccessorAt(0, first_true_block_);
   1003     compare->SetSuccessorAt(1, first_false_block_);
   1004   }
   1005   builder()->FinishCurrentBlock(compare);
   1006   needs_compare_ = false;
   1007   return compare;
   1008 }
   1009 
   1010 
   1011 void HGraphBuilder::IfBuilder::Or() {
   1012   DCHECK(!needs_compare_);
   1013   DCHECK(!did_and_);
   1014   did_or_ = true;
   1015   HEnvironment* env = first_false_block_->last_environment();
   1016   if (split_edge_merge_block_ == NULL) {
   1017     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
   1018     builder()->GotoNoSimulate(first_true_block_, split_edge_merge_block_);
   1019     first_true_block_ = split_edge_merge_block_;
   1020   }
   1021   builder()->set_current_block(first_false_block_);
   1022   first_false_block_ = builder()->CreateBasicBlock(env->Copy());
   1023 }
   1024 
   1025 
   1026 void HGraphBuilder::IfBuilder::And() {
   1027   DCHECK(!needs_compare_);
   1028   DCHECK(!did_or_);
   1029   did_and_ = true;
   1030   HEnvironment* env = first_false_block_->last_environment();
   1031   if (split_edge_merge_block_ == NULL) {
   1032     split_edge_merge_block_ = builder()->CreateBasicBlock(env->Copy());
   1033     builder()->GotoNoSimulate(first_false_block_, split_edge_merge_block_);
   1034     first_false_block_ = split_edge_merge_block_;
   1035   }
   1036   builder()->set_current_block(first_true_block_);
   1037   first_true_block_ = builder()->CreateBasicBlock(env->Copy());
   1038 }
   1039 
   1040 
   1041 void HGraphBuilder::IfBuilder::CaptureContinuation(
   1042     HIfContinuation* continuation) {
   1043   DCHECK(!did_else_if_);
   1044   DCHECK(!finished_);
   1045   DCHECK(!captured_);
   1046 
   1047   HBasicBlock* true_block = NULL;
   1048   HBasicBlock* false_block = NULL;
   1049   Finish(&true_block, &false_block);
   1050   DCHECK(true_block != NULL);
   1051   DCHECK(false_block != NULL);
   1052   continuation->Capture(true_block, false_block);
   1053   captured_ = true;
   1054   builder()->set_current_block(NULL);
   1055   End();
   1056 }
   1057 
   1058 
   1059 void HGraphBuilder::IfBuilder::JoinContinuation(HIfContinuation* continuation) {
   1060   DCHECK(!did_else_if_);
   1061   DCHECK(!finished_);
   1062   DCHECK(!captured_);
   1063   HBasicBlock* true_block = NULL;
   1064   HBasicBlock* false_block = NULL;
   1065   Finish(&true_block, &false_block);
   1066   merge_at_join_blocks_ = NULL;
   1067   if (true_block != NULL && !true_block->IsFinished()) {
   1068     DCHECK(continuation->IsTrueReachable());
   1069     builder()->GotoNoSimulate(true_block, continuation->true_branch());
   1070   }
   1071   if (false_block != NULL && !false_block->IsFinished()) {
   1072     DCHECK(continuation->IsFalseReachable());
   1073     builder()->GotoNoSimulate(false_block, continuation->false_branch());
   1074   }
   1075   captured_ = true;
   1076   End();
   1077 }
   1078 
   1079 
   1080 void HGraphBuilder::IfBuilder::Then() {
   1081   DCHECK(!captured_);
   1082   DCHECK(!finished_);
   1083   did_then_ = true;
   1084   if (needs_compare_) {
   1085     // Handle if's without any expressions, they jump directly to the "else"
   1086     // branch. However, we must pretend that the "then" branch is reachable,
   1087     // so that the graph builder visits it and sees any live range extending
   1088     // constructs within it.
   1089     HConstant* constant_false = builder()->graph()->GetConstantFalse();
   1090     ToBooleanHints boolean_type = ToBooleanHint::kBoolean;
   1091     HBranch* branch = builder()->New<HBranch>(
   1092         constant_false, boolean_type, first_true_block_, first_false_block_);
   1093     builder()->FinishCurrentBlock(branch);
   1094   }
   1095   builder()->set_current_block(first_true_block_);
   1096   pending_merge_block_ = true;
   1097 }
   1098 
   1099 
   1100 void HGraphBuilder::IfBuilder::Else() {
   1101   DCHECK(did_then_);
   1102   DCHECK(!captured_);
   1103   DCHECK(!finished_);
   1104   AddMergeAtJoinBlock(false);
   1105   builder()->set_current_block(first_false_block_);
   1106   pending_merge_block_ = true;
   1107   did_else_ = true;
   1108 }
   1109 
   1110 void HGraphBuilder::IfBuilder::Deopt(DeoptimizeReason reason) {
   1111   DCHECK(did_then_);
   1112   builder()->Add<HDeoptimize>(reason, Deoptimizer::EAGER);
   1113   AddMergeAtJoinBlock(true);
   1114 }
   1115 
   1116 
   1117 void HGraphBuilder::IfBuilder::Return(HValue* value) {
   1118   HValue* parameter_count = builder()->graph()->GetConstantMinus1();
   1119   builder()->FinishExitCurrentBlock(
   1120       builder()->New<HReturn>(value, parameter_count));
   1121   AddMergeAtJoinBlock(false);
   1122 }
   1123 
   1124 
   1125 void HGraphBuilder::IfBuilder::AddMergeAtJoinBlock(bool deopt) {
   1126   if (!pending_merge_block_) return;
   1127   HBasicBlock* block = builder()->current_block();
   1128   DCHECK(block == NULL || !block->IsFinished());
   1129   MergeAtJoinBlock* record = new (builder()->zone())
   1130       MergeAtJoinBlock(block, deopt, merge_at_join_blocks_);
   1131   merge_at_join_blocks_ = record;
   1132   if (block != NULL) {
   1133     DCHECK(block->end() == NULL);
   1134     if (deopt) {
   1135       normal_merge_at_join_block_count_++;
   1136     } else {
   1137       deopt_merge_at_join_block_count_++;
   1138     }
   1139   }
   1140   builder()->set_current_block(NULL);
   1141   pending_merge_block_ = false;
   1142 }
   1143 
   1144 
   1145 void HGraphBuilder::IfBuilder::Finish() {
   1146   DCHECK(!finished_);
   1147   if (!did_then_) {
   1148     Then();
   1149   }
   1150   AddMergeAtJoinBlock(false);
   1151   if (!did_else_) {
   1152     Else();
   1153     AddMergeAtJoinBlock(false);
   1154   }
   1155   finished_ = true;
   1156 }
   1157 
   1158 
   1159 void HGraphBuilder::IfBuilder::Finish(HBasicBlock** then_continuation,
   1160                                       HBasicBlock** else_continuation) {
   1161   Finish();
   1162 
   1163   MergeAtJoinBlock* else_record = merge_at_join_blocks_;
   1164   if (else_continuation != NULL) {
   1165     *else_continuation = else_record->block_;
   1166   }
   1167   MergeAtJoinBlock* then_record = else_record->next_;
   1168   if (then_continuation != NULL) {
   1169     *then_continuation = then_record->block_;
   1170   }
   1171   DCHECK(then_record->next_ == NULL);
   1172 }
   1173 
   1174 
   1175 void HGraphBuilder::IfBuilder::EndUnreachable() {
   1176   if (captured_) return;
   1177   Finish();
   1178   builder()->set_current_block(nullptr);
   1179 }
   1180 
   1181 
   1182 void HGraphBuilder::IfBuilder::End() {
   1183   if (captured_) return;
   1184   Finish();
   1185 
   1186   int total_merged_blocks = normal_merge_at_join_block_count_ +
   1187     deopt_merge_at_join_block_count_;
   1188   DCHECK(total_merged_blocks >= 1);
   1189   HBasicBlock* merge_block =
   1190       total_merged_blocks == 1 ? NULL : builder()->graph()->CreateBasicBlock();
   1191 
   1192   // Merge non-deopt blocks first to ensure environment has right size for
   1193   // padding.
   1194   MergeAtJoinBlock* current = merge_at_join_blocks_;
   1195   while (current != NULL) {
   1196     if (!current->deopt_ && current->block_ != NULL) {
   1197       // If there is only one block that makes it through to the end of the
   1198       // if, then just set it as the current block and continue rather then
   1199       // creating an unnecessary merge block.
   1200       if (total_merged_blocks == 1) {
   1201         builder()->set_current_block(current->block_);
   1202         return;
   1203       }
   1204       builder()->GotoNoSimulate(current->block_, merge_block);
   1205     }
   1206     current = current->next_;
   1207   }
   1208 
   1209   // Merge deopt blocks, padding when necessary.
   1210   current = merge_at_join_blocks_;
   1211   while (current != NULL) {
   1212     if (current->deopt_ && current->block_ != NULL) {
   1213       current->block_->FinishExit(
   1214           HAbnormalExit::New(builder()->isolate(), builder()->zone(), NULL),
   1215           SourcePosition::Unknown());
   1216     }
   1217     current = current->next_;
   1218   }
   1219   builder()->set_current_block(merge_block);
   1220 }
   1221 
   1222 
   1223 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder) {
   1224   Initialize(builder, NULL, kWhileTrue, NULL);
   1225 }
   1226 
   1227 
   1228 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
   1229                                         LoopBuilder::Direction direction) {
   1230   Initialize(builder, context, direction, builder->graph()->GetConstant1());
   1231 }
   1232 
   1233 
   1234 HGraphBuilder::LoopBuilder::LoopBuilder(HGraphBuilder* builder, HValue* context,
   1235                                         LoopBuilder::Direction direction,
   1236                                         HValue* increment_amount) {
   1237   Initialize(builder, context, direction, increment_amount);
   1238   increment_amount_ = increment_amount;
   1239 }
   1240 
   1241 
   1242 void HGraphBuilder::LoopBuilder::Initialize(HGraphBuilder* builder,
   1243                                             HValue* context,
   1244                                             Direction direction,
   1245                                             HValue* increment_amount) {
   1246   builder_ = builder;
   1247   context_ = context;
   1248   direction_ = direction;
   1249   increment_amount_ = increment_amount;
   1250 
   1251   finished_ = false;
   1252   header_block_ = builder->CreateLoopHeaderBlock();
   1253   body_block_ = NULL;
   1254   exit_block_ = NULL;
   1255   exit_trampoline_block_ = NULL;
   1256 }
   1257 
   1258 
   1259 HValue* HGraphBuilder::LoopBuilder::BeginBody(
   1260     HValue* initial,
   1261     HValue* terminating,
   1262     Token::Value token) {
   1263   DCHECK(direction_ != kWhileTrue);
   1264   HEnvironment* env = builder_->environment();
   1265   phi_ = header_block_->AddNewPhi(env->values()->length());
   1266   phi_->AddInput(initial);
   1267   env->Push(initial);
   1268   builder_->GotoNoSimulate(header_block_);
   1269 
   1270   HEnvironment* body_env = env->Copy();
   1271   HEnvironment* exit_env = env->Copy();
   1272   // Remove the phi from the expression stack
   1273   body_env->Pop();
   1274   exit_env->Pop();
   1275   body_block_ = builder_->CreateBasicBlock(body_env);
   1276   exit_block_ = builder_->CreateBasicBlock(exit_env);
   1277 
   1278   builder_->set_current_block(header_block_);
   1279   env->Pop();
   1280   builder_->FinishCurrentBlock(builder_->New<HCompareNumericAndBranch>(
   1281           phi_, terminating, token, body_block_, exit_block_));
   1282 
   1283   builder_->set_current_block(body_block_);
   1284   if (direction_ == kPreIncrement || direction_ == kPreDecrement) {
   1285     Isolate* isolate = builder_->isolate();
   1286     HValue* one = builder_->graph()->GetConstant1();
   1287     if (direction_ == kPreIncrement) {
   1288       increment_ = HAdd::New(isolate, zone(), context_, phi_, one);
   1289     } else {
   1290       increment_ = HSub::New(isolate, zone(), context_, phi_, one);
   1291     }
   1292     increment_->ClearFlag(HValue::kCanOverflow);
   1293     builder_->AddInstruction(increment_);
   1294     return increment_;
   1295   } else {
   1296     return phi_;
   1297   }
   1298 }
   1299 
   1300 
   1301 void HGraphBuilder::LoopBuilder::BeginBody(int drop_count) {
   1302   DCHECK(direction_ == kWhileTrue);
   1303   HEnvironment* env = builder_->environment();
   1304   builder_->GotoNoSimulate(header_block_);
   1305   builder_->set_current_block(header_block_);
   1306   env->Drop(drop_count);
   1307 }
   1308 
   1309 
   1310 void HGraphBuilder::LoopBuilder::Break() {
   1311   if (exit_trampoline_block_ == NULL) {
   1312     // Its the first time we saw a break.
   1313     if (direction_ == kWhileTrue) {
   1314       HEnvironment* env = builder_->environment()->Copy();
   1315       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
   1316     } else {
   1317       HEnvironment* env = exit_block_->last_environment()->Copy();
   1318       exit_trampoline_block_ = builder_->CreateBasicBlock(env);
   1319       builder_->GotoNoSimulate(exit_block_, exit_trampoline_block_);
   1320     }
   1321   }
   1322 
   1323   builder_->GotoNoSimulate(exit_trampoline_block_);
   1324   builder_->set_current_block(NULL);
   1325 }
   1326 
   1327 
   1328 void HGraphBuilder::LoopBuilder::EndBody() {
   1329   DCHECK(!finished_);
   1330 
   1331   if (direction_ == kPostIncrement || direction_ == kPostDecrement) {
   1332     Isolate* isolate = builder_->isolate();
   1333     if (direction_ == kPostIncrement) {
   1334       increment_ =
   1335           HAdd::New(isolate, zone(), context_, phi_, increment_amount_);
   1336     } else {
   1337       increment_ =
   1338           HSub::New(isolate, zone(), context_, phi_, increment_amount_);
   1339     }
   1340     increment_->ClearFlag(HValue::kCanOverflow);
   1341     builder_->AddInstruction(increment_);
   1342   }
   1343 
   1344   if (direction_ != kWhileTrue) {
   1345     // Push the new increment value on the expression stack to merge into
   1346     // the phi.
   1347     builder_->environment()->Push(increment_);
   1348   }
   1349   HBasicBlock* last_block = builder_->current_block();
   1350   builder_->GotoNoSimulate(last_block, header_block_);
   1351   header_block_->loop_information()->RegisterBackEdge(last_block);
   1352 
   1353   if (exit_trampoline_block_ != NULL) {
   1354     builder_->set_current_block(exit_trampoline_block_);
   1355   } else {
   1356     builder_->set_current_block(exit_block_);
   1357   }
   1358   finished_ = true;
   1359 }
   1360 
   1361 
   1362 HGraph* HGraphBuilder::CreateGraph() {
   1363   DCHECK(!FLAG_minimal);
   1364   graph_ = new (zone()) HGraph(info_, descriptor_);
   1365   if (FLAG_hydrogen_stats) isolate()->GetHStatistics()->Initialize(info_);
   1366   if (!info_->IsStub() && is_tracking_positions()) {
   1367     TraceInlinedFunction(info_->shared_info(), SourcePosition::Unknown(),
   1368                          SourcePosition::kNotInlined);
   1369   }
   1370   CompilationPhase phase("H_Block building", info_);
   1371   set_current_block(graph()->entry_block());
   1372   if (!BuildGraph()) return NULL;
   1373   graph()->FinalizeUniqueness();
   1374   return graph_;
   1375 }
   1376 
   1377 void HGraphBuilder::TraceInlinedFunction(Handle<SharedFunctionInfo> shared,
   1378                                          SourcePosition position,
   1379                                          int inlining_id) {
   1380   DCHECK(is_tracking_positions());
   1381 
   1382   if (!shared->script()->IsUndefined(isolate())) {
   1383     Handle<Script> script(Script::cast(shared->script()), isolate());
   1384 
   1385     if (FLAG_hydrogen_track_positions &&
   1386         !script->source()->IsUndefined(isolate())) {
   1387       CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
   1388       Object* source_name = script->name();
   1389       OFStream os(tracing_scope.file());
   1390       os << "--- FUNCTION SOURCE (";
   1391       if (source_name->IsString()) {
   1392         os << String::cast(source_name)->ToCString().get() << ":";
   1393       }
   1394       os << shared->DebugName()->ToCString().get() << ") id{";
   1395       os << info_->optimization_id() << "," << inlining_id << "} ---\n";
   1396       {
   1397         DisallowHeapAllocation no_allocation;
   1398         int start = shared->start_position();
   1399         int len = shared->end_position() - start;
   1400         String::SubStringRange source(String::cast(script->source()), start,
   1401                                       len);
   1402         for (const auto& c : source) {
   1403           os << AsReversiblyEscapedUC16(c);
   1404         }
   1405       }
   1406 
   1407       os << "\n--- END ---\n";
   1408     }
   1409   }
   1410 
   1411   if (FLAG_hydrogen_track_positions &&
   1412       inlining_id != SourcePosition::kNotInlined) {
   1413     CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
   1414     OFStream os(tracing_scope.file());
   1415     os << "INLINE (" << shared->DebugName()->ToCString().get() << ") id{"
   1416        << info_->optimization_id() << "," << inlining_id << "} AS "
   1417        << inlining_id << " AT " << position.ScriptOffset() << std::endl;
   1418   }
   1419 }
   1420 
   1421 HInstruction* HGraphBuilder::AddInstruction(HInstruction* instr) {
   1422   DCHECK(current_block() != NULL);
   1423   DCHECK(!FLAG_hydrogen_track_positions || position_.IsKnown() ||
   1424          !info_->IsOptimizing());
   1425   current_block()->AddInstruction(instr, source_position());
   1426   if (graph()->IsInsideNoSideEffectsScope()) {
   1427     instr->SetFlag(HValue::kHasNoObservableSideEffects);
   1428   }
   1429   return instr;
   1430 }
   1431 
   1432 
   1433 void HGraphBuilder::FinishCurrentBlock(HControlInstruction* last) {
   1434   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
   1435          position_.IsKnown());
   1436   current_block()->Finish(last, source_position());
   1437   if (last->IsReturn() || last->IsAbnormalExit()) {
   1438     set_current_block(NULL);
   1439   }
   1440 }
   1441 
   1442 
   1443 void HGraphBuilder::FinishExitCurrentBlock(HControlInstruction* instruction) {
   1444   DCHECK(!FLAG_hydrogen_track_positions || !info_->IsOptimizing() ||
   1445          position_.IsKnown());
   1446   current_block()->FinishExit(instruction, source_position());
   1447   if (instruction->IsReturn() || instruction->IsAbnormalExit()) {
   1448     set_current_block(NULL);
   1449   }
   1450 }
   1451 
   1452 
   1453 void HGraphBuilder::AddIncrementCounter(StatsCounter* counter) {
   1454   if (FLAG_native_code_counters && counter->Enabled()) {
   1455     HValue* reference = Add<HConstant>(ExternalReference(counter));
   1456     HValue* old_value =
   1457         Add<HLoadNamedField>(reference, nullptr, HObjectAccess::ForCounter());
   1458     HValue* new_value = AddUncasted<HAdd>(old_value, graph()->GetConstant1());
   1459     new_value->ClearFlag(HValue::kCanOverflow);  // Ignore counter overflow
   1460     Add<HStoreNamedField>(reference, HObjectAccess::ForCounter(),
   1461                           new_value, STORE_TO_INITIALIZED_ENTRY);
   1462   }
   1463 }
   1464 
   1465 
   1466 void HGraphBuilder::AddSimulate(BailoutId id,
   1467                                 RemovableSimulate removable) {
   1468   DCHECK(current_block() != NULL);
   1469   DCHECK(!graph()->IsInsideNoSideEffectsScope());
   1470   current_block()->AddNewSimulate(id, source_position(), removable);
   1471 }
   1472 
   1473 
   1474 HBasicBlock* HGraphBuilder::CreateBasicBlock(HEnvironment* env) {
   1475   HBasicBlock* b = graph()->CreateBasicBlock();
   1476   b->SetInitialEnvironment(env);
   1477   return b;
   1478 }
   1479 
   1480 
   1481 HBasicBlock* HGraphBuilder::CreateLoopHeaderBlock() {
   1482   HBasicBlock* header = graph()->CreateBasicBlock();
   1483   HEnvironment* entry_env = environment()->CopyAsLoopHeader(header);
   1484   header->SetInitialEnvironment(entry_env);
   1485   header->AttachLoopInformation();
   1486   return header;
   1487 }
   1488 
   1489 
   1490 HValue* HGraphBuilder::BuildGetElementsKind(HValue* object) {
   1491   HValue* map = Add<HLoadNamedField>(object, nullptr, HObjectAccess::ForMap());
   1492 
   1493   HValue* bit_field2 =
   1494       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField2());
   1495   return BuildDecodeField<Map::ElementsKindBits>(bit_field2);
   1496 }
   1497 
   1498 
   1499 HValue* HGraphBuilder::BuildEnumLength(HValue* map) {
   1500   NoObservableSideEffectsScope scope(this);
   1501   HValue* bit_field3 =
   1502       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField3());
   1503   return BuildDecodeField<Map::EnumLengthBits>(bit_field3);
   1504 }
   1505 
   1506 
   1507 HValue* HGraphBuilder::BuildCheckHeapObject(HValue* obj) {
   1508   if (obj->type().IsHeapObject()) return obj;
   1509   return Add<HCheckHeapObject>(obj);
   1510 }
   1511 
   1512 void HGraphBuilder::FinishExitWithHardDeoptimization(DeoptimizeReason reason) {
   1513   Add<HDeoptimize>(reason, Deoptimizer::EAGER);
   1514   FinishExitCurrentBlock(New<HAbnormalExit>());
   1515 }
   1516 
   1517 
   1518 HValue* HGraphBuilder::BuildCheckString(HValue* string) {
   1519   if (!string->type().IsString()) {
   1520     DCHECK(!string->IsConstant() ||
   1521            !HConstant::cast(string)->HasStringValue());
   1522     BuildCheckHeapObject(string);
   1523     return Add<HCheckInstanceType>(string, HCheckInstanceType::IS_STRING);
   1524   }
   1525   return string;
   1526 }
   1527 
   1528 HValue* HGraphBuilder::BuildWrapReceiver(HValue* object, HValue* checked) {
   1529   if (object->type().IsJSObject()) return object;
   1530   HValue* function = checked->ActualValue();
   1531   if (function->IsConstant() &&
   1532       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   1533     Handle<JSFunction> f = Handle<JSFunction>::cast(
   1534         HConstant::cast(function)->handle(isolate()));
   1535     SharedFunctionInfo* shared = f->shared();
   1536     if (is_strict(shared->language_mode()) || shared->native()) return object;
   1537   }
   1538   return Add<HWrapReceiver>(object, checked);
   1539 }
   1540 
   1541 
   1542 HValue* HGraphBuilder::BuildCheckAndGrowElementsCapacity(
   1543     HValue* object, HValue* elements, ElementsKind kind, HValue* length,
   1544     HValue* capacity, HValue* key) {
   1545   HValue* max_gap = Add<HConstant>(static_cast<int32_t>(JSObject::kMaxGap));
   1546   HValue* max_capacity = AddUncasted<HAdd>(capacity, max_gap);
   1547   Add<HBoundsCheck>(key, max_capacity);
   1548 
   1549   HValue* new_capacity = BuildNewElementsCapacity(key);
   1550   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind, kind,
   1551                                                    length, new_capacity);
   1552   return new_elements;
   1553 }
   1554 
   1555 
   1556 HValue* HGraphBuilder::BuildCheckForCapacityGrow(
   1557     HValue* object,
   1558     HValue* elements,
   1559     ElementsKind kind,
   1560     HValue* length,
   1561     HValue* key,
   1562     bool is_js_array,
   1563     PropertyAccessType access_type) {
   1564   IfBuilder length_checker(this);
   1565 
   1566   Token::Value token = IsHoleyElementsKind(kind) ? Token::GTE : Token::EQ;
   1567   length_checker.If<HCompareNumericAndBranch>(key, length, token);
   1568 
   1569   length_checker.Then();
   1570 
   1571   HValue* current_capacity = AddLoadFixedArrayLength(elements);
   1572 
   1573   if (top_info()->IsStub()) {
   1574     IfBuilder capacity_checker(this);
   1575     capacity_checker.If<HCompareNumericAndBranch>(key, current_capacity,
   1576                                                   Token::GTE);
   1577     capacity_checker.Then();
   1578     HValue* new_elements = BuildCheckAndGrowElementsCapacity(
   1579         object, elements, kind, length, current_capacity, key);
   1580     environment()->Push(new_elements);
   1581     capacity_checker.Else();
   1582     environment()->Push(elements);
   1583     capacity_checker.End();
   1584   } else {
   1585     HValue* result = Add<HMaybeGrowElements>(
   1586         object, elements, key, current_capacity, is_js_array, kind);
   1587     environment()->Push(result);
   1588   }
   1589 
   1590   if (is_js_array) {
   1591     HValue* new_length = AddUncasted<HAdd>(key, graph_->GetConstant1());
   1592     new_length->ClearFlag(HValue::kCanOverflow);
   1593 
   1594     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(kind),
   1595                           new_length);
   1596   }
   1597 
   1598   if (access_type == STORE && kind == FAST_SMI_ELEMENTS) {
   1599     HValue* checked_elements = environment()->Top();
   1600 
   1601     // Write zero to ensure that the new element is initialized with some smi.
   1602     Add<HStoreKeyed>(checked_elements, key, graph()->GetConstant0(), nullptr,
   1603                      kind);
   1604   }
   1605 
   1606   length_checker.Else();
   1607   Add<HBoundsCheck>(key, length);
   1608 
   1609   environment()->Push(elements);
   1610   length_checker.End();
   1611 
   1612   return environment()->Pop();
   1613 }
   1614 
   1615 
   1616 HValue* HGraphBuilder::BuildCopyElementsOnWrite(HValue* object,
   1617                                                 HValue* elements,
   1618                                                 ElementsKind kind,
   1619                                                 HValue* length) {
   1620   Factory* factory = isolate()->factory();
   1621 
   1622   IfBuilder cow_checker(this);
   1623 
   1624   cow_checker.If<HCompareMap>(elements, factory->fixed_cow_array_map());
   1625   cow_checker.Then();
   1626 
   1627   HValue* capacity = AddLoadFixedArrayLength(elements);
   1628 
   1629   HValue* new_elements = BuildGrowElementsCapacity(object, elements, kind,
   1630                                                    kind, length, capacity);
   1631 
   1632   environment()->Push(new_elements);
   1633 
   1634   cow_checker.Else();
   1635 
   1636   environment()->Push(elements);
   1637 
   1638   cow_checker.End();
   1639 
   1640   return environment()->Pop();
   1641 }
   1642 
   1643 HValue* HGraphBuilder::BuildElementIndexHash(HValue* index) {
   1644   int32_t seed_value = static_cast<uint32_t>(isolate()->heap()->HashSeed());
   1645   HValue* seed = Add<HConstant>(seed_value);
   1646   HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, index, seed);
   1647 
   1648   // hash = ~hash + (hash << 15);
   1649   HValue* shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(15));
   1650   HValue* not_hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash,
   1651                                            graph()->GetConstantMinus1());
   1652   hash = AddUncasted<HAdd>(shifted_hash, not_hash);
   1653 
   1654   // hash = hash ^ (hash >> 12);
   1655   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(12));
   1656   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1657 
   1658   // hash = hash + (hash << 2);
   1659   shifted_hash = AddUncasted<HShl>(hash, Add<HConstant>(2));
   1660   hash = AddUncasted<HAdd>(hash, shifted_hash);
   1661 
   1662   // hash = hash ^ (hash >> 4);
   1663   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(4));
   1664   hash = AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1665 
   1666   // hash = hash * 2057;
   1667   hash = AddUncasted<HMul>(hash, Add<HConstant>(2057));
   1668   hash->ClearFlag(HValue::kCanOverflow);
   1669 
   1670   // hash = hash ^ (hash >> 16);
   1671   shifted_hash = AddUncasted<HShr>(hash, Add<HConstant>(16));
   1672   return AddUncasted<HBitwise>(Token::BIT_XOR, hash, shifted_hash);
   1673 }
   1674 
   1675 HValue* HGraphBuilder::BuildUncheckedDictionaryElementLoad(HValue* receiver,
   1676                                                            HValue* elements,
   1677                                                            HValue* key,
   1678                                                            HValue* hash) {
   1679   HValue* capacity =
   1680       Add<HLoadKeyed>(elements, Add<HConstant>(NameDictionary::kCapacityIndex),
   1681                       nullptr, nullptr, FAST_ELEMENTS);
   1682 
   1683   HValue* mask = AddUncasted<HSub>(capacity, graph()->GetConstant1());
   1684   mask->ChangeRepresentation(Representation::Integer32());
   1685   mask->ClearFlag(HValue::kCanOverflow);
   1686 
   1687   HValue* entry = hash;
   1688   HValue* count = graph()->GetConstant1();
   1689   Push(entry);
   1690   Push(count);
   1691 
   1692   HIfContinuation return_or_loop_continuation(graph()->CreateBasicBlock(),
   1693                                               graph()->CreateBasicBlock());
   1694   HIfContinuation found_key_match_continuation(graph()->CreateBasicBlock(),
   1695                                                graph()->CreateBasicBlock());
   1696   LoopBuilder probe_loop(this);
   1697   probe_loop.BeginBody(2);  // Drop entry, count from last environment to
   1698                             // appease live range building without simulates.
   1699 
   1700   count = Pop();
   1701   entry = Pop();
   1702   entry = AddUncasted<HBitwise>(Token::BIT_AND, entry, mask);
   1703   int entry_size = SeededNumberDictionary::kEntrySize;
   1704   HValue* base_index = AddUncasted<HMul>(entry, Add<HConstant>(entry_size));
   1705   base_index->ClearFlag(HValue::kCanOverflow);
   1706   int start_offset = SeededNumberDictionary::kElementsStartIndex;
   1707   HValue* key_index =
   1708       AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset));
   1709   key_index->ClearFlag(HValue::kCanOverflow);
   1710 
   1711   HValue* candidate_key =
   1712       Add<HLoadKeyed>(elements, key_index, nullptr, nullptr, FAST_ELEMENTS);
   1713   IfBuilder if_undefined(this);
   1714   if_undefined.If<HCompareObjectEqAndBranch>(candidate_key,
   1715                                              graph()->GetConstantUndefined());
   1716   if_undefined.Then();
   1717   {
   1718     // element == undefined means "not found". Call the runtime.
   1719     // TODO(jkummerow): walk the prototype chain instead.
   1720     Add<HPushArguments>(receiver, key);
   1721     Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kKeyedGetProperty),
   1722                            2));
   1723   }
   1724   if_undefined.Else();
   1725   {
   1726     IfBuilder if_match(this);
   1727     if_match.If<HCompareObjectEqAndBranch>(candidate_key, key);
   1728     if_match.Then();
   1729     if_match.Else();
   1730 
   1731     // Update non-internalized string in the dictionary with internalized key?
   1732     IfBuilder if_update_with_internalized(this);
   1733     HValue* smi_check =
   1734         if_update_with_internalized.IfNot<HIsSmiAndBranch>(candidate_key);
   1735     if_update_with_internalized.And();
   1736     HValue* map = AddLoadMap(candidate_key, smi_check);
   1737     HValue* instance_type =
   1738         Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
   1739     HValue* not_internalized_bit = AddUncasted<HBitwise>(
   1740         Token::BIT_AND, instance_type,
   1741         Add<HConstant>(static_cast<int>(kIsNotInternalizedMask)));
   1742     if_update_with_internalized.If<HCompareNumericAndBranch>(
   1743         not_internalized_bit, graph()->GetConstant0(), Token::NE);
   1744     if_update_with_internalized.And();
   1745     if_update_with_internalized.IfNot<HCompareObjectEqAndBranch>(
   1746         candidate_key, graph()->GetConstantHole());
   1747     if_update_with_internalized.AndIf<HStringCompareAndBranch>(candidate_key,
   1748                                                                key, Token::EQ);
   1749     if_update_with_internalized.Then();
   1750     // Replace a key that is a non-internalized string by the equivalent
   1751     // internalized string for faster further lookups.
   1752     Add<HStoreKeyed>(elements, key_index, key, nullptr, FAST_ELEMENTS);
   1753     if_update_with_internalized.Else();
   1754 
   1755     if_update_with_internalized.JoinContinuation(&found_key_match_continuation);
   1756     if_match.JoinContinuation(&found_key_match_continuation);
   1757 
   1758     IfBuilder found_key_match(this, &found_key_match_continuation);
   1759     found_key_match.Then();
   1760     // Key at current probe matches. Relevant bits in the |details| field must
   1761     // be zero, otherwise the dictionary element requires special handling.
   1762     HValue* details_index =
   1763         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 2));
   1764     details_index->ClearFlag(HValue::kCanOverflow);
   1765     HValue* details = Add<HLoadKeyed>(elements, details_index, nullptr, nullptr,
   1766                                       FAST_ELEMENTS);
   1767     int details_mask = PropertyDetails::TypeField::kMask;
   1768     details = AddUncasted<HBitwise>(Token::BIT_AND, details,
   1769                                     Add<HConstant>(details_mask));
   1770     IfBuilder details_compare(this);
   1771     details_compare.If<HCompareNumericAndBranch>(
   1772         details, graph()->GetConstant0(), Token::EQ);
   1773     details_compare.Then();
   1774     HValue* result_index =
   1775         AddUncasted<HAdd>(base_index, Add<HConstant>(start_offset + 1));
   1776     result_index->ClearFlag(HValue::kCanOverflow);
   1777     Push(Add<HLoadKeyed>(elements, result_index, nullptr, nullptr,
   1778                          FAST_ELEMENTS));
   1779     details_compare.Else();
   1780     Add<HPushArguments>(receiver, key);
   1781     Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kKeyedGetProperty),
   1782                            2));
   1783     details_compare.End();
   1784 
   1785     found_key_match.Else();
   1786     found_key_match.JoinContinuation(&return_or_loop_continuation);
   1787   }
   1788   if_undefined.JoinContinuation(&return_or_loop_continuation);
   1789 
   1790   IfBuilder return_or_loop(this, &return_or_loop_continuation);
   1791   return_or_loop.Then();
   1792   probe_loop.Break();
   1793 
   1794   return_or_loop.Else();
   1795   entry = AddUncasted<HAdd>(entry, count);
   1796   entry->ClearFlag(HValue::kCanOverflow);
   1797   count = AddUncasted<HAdd>(count, graph()->GetConstant1());
   1798   count->ClearFlag(HValue::kCanOverflow);
   1799   Push(entry);
   1800   Push(count);
   1801 
   1802   probe_loop.EndBody();
   1803 
   1804   return_or_loop.End();
   1805 
   1806   return Pop();
   1807 }
   1808 
   1809 HValue* HGraphBuilder::BuildCreateIterResultObject(HValue* value,
   1810                                                    HValue* done) {
   1811   NoObservableSideEffectsScope scope(this);
   1812 
   1813   // Allocate the JSIteratorResult object.
   1814   HValue* result =
   1815       Add<HAllocate>(Add<HConstant>(JSIteratorResult::kSize), HType::JSObject(),
   1816                      NOT_TENURED, JS_OBJECT_TYPE, graph()->GetConstant0());
   1817 
   1818   // Initialize the JSIteratorResult object.
   1819   HValue* native_context = BuildGetNativeContext();
   1820   HValue* map = Add<HLoadNamedField>(
   1821       native_context, nullptr,
   1822       HObjectAccess::ForContextSlot(Context::ITERATOR_RESULT_MAP_INDEX));
   1823   Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
   1824   HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
   1825   Add<HStoreNamedField>(result, HObjectAccess::ForPropertiesPointer(),
   1826                         empty_fixed_array);
   1827   Add<HStoreNamedField>(result, HObjectAccess::ForElementsPointer(),
   1828                         empty_fixed_array);
   1829   Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
   1830                                     JSIteratorResult::kValueOffset),
   1831                         value);
   1832   Add<HStoreNamedField>(result, HObjectAccess::ForObservableJSObjectOffset(
   1833                                     JSIteratorResult::kDoneOffset),
   1834                         done);
   1835   STATIC_ASSERT(JSIteratorResult::kSize == 5 * kPointerSize);
   1836   return result;
   1837 }
   1838 
   1839 
   1840 HValue* HGraphBuilder::BuildNumberToString(HValue* object, AstType* type) {
   1841   NoObservableSideEffectsScope scope(this);
   1842 
   1843   // Convert constant numbers at compile time.
   1844   if (object->IsConstant() && HConstant::cast(object)->HasNumberValue()) {
   1845     Handle<Object> number = HConstant::cast(object)->handle(isolate());
   1846     Handle<String> result = isolate()->factory()->NumberToString(number);
   1847     return Add<HConstant>(result);
   1848   }
   1849 
   1850   // Create a joinable continuation.
   1851   HIfContinuation found(graph()->CreateBasicBlock(),
   1852                         graph()->CreateBasicBlock());
   1853 
   1854   // Load the number string cache.
   1855   HValue* number_string_cache =
   1856       Add<HLoadRoot>(Heap::kNumberStringCacheRootIndex);
   1857 
   1858   // Make the hash mask from the length of the number string cache. It
   1859   // contains two elements (number and string) for each cache entry.
   1860   HValue* mask = AddLoadFixedArrayLength(number_string_cache);
   1861   mask->set_type(HType::Smi());
   1862   mask = AddUncasted<HSar>(mask, graph()->GetConstant1());
   1863   mask = AddUncasted<HSub>(mask, graph()->GetConstant1());
   1864 
   1865   // Check whether object is a smi.
   1866   IfBuilder if_objectissmi(this);
   1867   if_objectissmi.If<HIsSmiAndBranch>(object);
   1868   if_objectissmi.Then();
   1869   {
   1870     // Compute hash for smi similar to smi_get_hash().
   1871     HValue* hash = AddUncasted<HBitwise>(Token::BIT_AND, object, mask);
   1872 
   1873     // Load the key.
   1874     HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
   1875     HValue* key = Add<HLoadKeyed>(number_string_cache, key_index, nullptr,
   1876                                   nullptr, FAST_ELEMENTS, ALLOW_RETURN_HOLE);
   1877 
   1878     // Check if object == key.
   1879     IfBuilder if_objectiskey(this);
   1880     if_objectiskey.If<HCompareObjectEqAndBranch>(object, key);
   1881     if_objectiskey.Then();
   1882     {
   1883       // Make the key_index available.
   1884       Push(key_index);
   1885     }
   1886     if_objectiskey.JoinContinuation(&found);
   1887   }
   1888   if_objectissmi.Else();
   1889   {
   1890     if (type->Is(AstType::SignedSmall())) {
   1891       if_objectissmi.Deopt(DeoptimizeReason::kExpectedSmi);
   1892     } else {
   1893       // Check if the object is a heap number.
   1894       IfBuilder if_objectisnumber(this);
   1895       HValue* objectisnumber = if_objectisnumber.If<HCompareMap>(
   1896           object, isolate()->factory()->heap_number_map());
   1897       if_objectisnumber.Then();
   1898       {
   1899         // Compute hash for heap number similar to double_get_hash().
   1900         HValue* low = Add<HLoadNamedField>(
   1901             object, objectisnumber,
   1902             HObjectAccess::ForHeapNumberValueLowestBits());
   1903         HValue* high = Add<HLoadNamedField>(
   1904             object, objectisnumber,
   1905             HObjectAccess::ForHeapNumberValueHighestBits());
   1906         HValue* hash = AddUncasted<HBitwise>(Token::BIT_XOR, low, high);
   1907         hash = AddUncasted<HBitwise>(Token::BIT_AND, hash, mask);
   1908 
   1909         // Load the key.
   1910         HValue* key_index = AddUncasted<HShl>(hash, graph()->GetConstant1());
   1911         HValue* key =
   1912             Add<HLoadKeyed>(number_string_cache, key_index, nullptr, nullptr,
   1913                             FAST_ELEMENTS, ALLOW_RETURN_HOLE);
   1914 
   1915         // Check if the key is a heap number and compare it with the object.
   1916         IfBuilder if_keyisnotsmi(this);
   1917         HValue* keyisnotsmi = if_keyisnotsmi.IfNot<HIsSmiAndBranch>(key);
   1918         if_keyisnotsmi.Then();
   1919         {
   1920           IfBuilder if_keyisheapnumber(this);
   1921           if_keyisheapnumber.If<HCompareMap>(
   1922               key, isolate()->factory()->heap_number_map());
   1923           if_keyisheapnumber.Then();
   1924           {
   1925             // Check if values of key and object match.
   1926             IfBuilder if_keyeqobject(this);
   1927             if_keyeqobject.If<HCompareNumericAndBranch>(
   1928                 Add<HLoadNamedField>(key, keyisnotsmi,
   1929                                      HObjectAccess::ForHeapNumberValue()),
   1930                 Add<HLoadNamedField>(object, objectisnumber,
   1931                                      HObjectAccess::ForHeapNumberValue()),
   1932                 Token::EQ);
   1933             if_keyeqobject.Then();
   1934             {
   1935               // Make the key_index available.
   1936               Push(key_index);
   1937             }
   1938             if_keyeqobject.JoinContinuation(&found);
   1939           }
   1940           if_keyisheapnumber.JoinContinuation(&found);
   1941         }
   1942         if_keyisnotsmi.JoinContinuation(&found);
   1943       }
   1944       if_objectisnumber.Else();
   1945       {
   1946         if (type->Is(AstType::Number())) {
   1947           if_objectisnumber.Deopt(DeoptimizeReason::kExpectedHeapNumber);
   1948         }
   1949       }
   1950       if_objectisnumber.JoinContinuation(&found);
   1951     }
   1952   }
   1953   if_objectissmi.JoinContinuation(&found);
   1954 
   1955   // Check for cache hit.
   1956   IfBuilder if_found(this, &found);
   1957   if_found.Then();
   1958   {
   1959     // Count number to string operation in native code.
   1960     AddIncrementCounter(isolate()->counters()->number_to_string_native());
   1961 
   1962     // Load the value in case of cache hit.
   1963     HValue* key_index = Pop();
   1964     HValue* value_index = AddUncasted<HAdd>(key_index, graph()->GetConstant1());
   1965     Push(Add<HLoadKeyed>(number_string_cache, value_index, nullptr, nullptr,
   1966                          FAST_ELEMENTS, ALLOW_RETURN_HOLE));
   1967   }
   1968   if_found.Else();
   1969   {
   1970     // Cache miss, fallback to runtime.
   1971     Add<HPushArguments>(object);
   1972     Push(Add<HCallRuntime>(
   1973             Runtime::FunctionForId(Runtime::kNumberToStringSkipCache),
   1974             1));
   1975   }
   1976   if_found.End();
   1977 
   1978   return Pop();
   1979 }
   1980 
   1981 HValue* HGraphBuilder::BuildToNumber(HValue* input) {
   1982   if (input->type().IsTaggedNumber() ||
   1983       input->representation().IsSpecialization()) {
   1984     return input;
   1985   }
   1986   Callable callable = CodeFactory::ToNumber(isolate());
   1987   HValue* stub = Add<HConstant>(callable.code());
   1988   HValue* values[] = {input};
   1989   HCallWithDescriptor* instr = Add<HCallWithDescriptor>(
   1990       stub, 0, callable.descriptor(), ArrayVector(values));
   1991   instr->set_type(HType::TaggedNumber());
   1992   return instr;
   1993 }
   1994 
   1995 
   1996 HValue* HGraphBuilder::BuildToObject(HValue* receiver) {
   1997   NoObservableSideEffectsScope scope(this);
   1998 
   1999   // Create a joinable continuation.
   2000   HIfContinuation wrap(graph()->CreateBasicBlock(),
   2001                        graph()->CreateBasicBlock());
   2002 
   2003   // Determine the proper global constructor function required to wrap
   2004   // {receiver} into a JSValue, unless {receiver} is already a {JSReceiver}, in
   2005   // which case we just return it.  Deopts to Runtime::kToObject if {receiver}
   2006   // is undefined or null.
   2007   IfBuilder receiver_is_smi(this);
   2008   receiver_is_smi.If<HIsSmiAndBranch>(receiver);
   2009   receiver_is_smi.Then();
   2010   {
   2011     // Use global Number function.
   2012     Push(Add<HConstant>(Context::NUMBER_FUNCTION_INDEX));
   2013   }
   2014   receiver_is_smi.Else();
   2015   {
   2016     // Determine {receiver} map and instance type.
   2017     HValue* receiver_map =
   2018         Add<HLoadNamedField>(receiver, nullptr, HObjectAccess::ForMap());
   2019     HValue* receiver_instance_type = Add<HLoadNamedField>(
   2020         receiver_map, nullptr, HObjectAccess::ForMapInstanceType());
   2021 
   2022     // First check whether {receiver} is already a spec object (fast case).
   2023     IfBuilder receiver_is_not_spec_object(this);
   2024     receiver_is_not_spec_object.If<HCompareNumericAndBranch>(
   2025         receiver_instance_type, Add<HConstant>(FIRST_JS_RECEIVER_TYPE),
   2026         Token::LT);
   2027     receiver_is_not_spec_object.Then();
   2028     {
   2029       // Load the constructor function index from the {receiver} map.
   2030       HValue* constructor_function_index = Add<HLoadNamedField>(
   2031           receiver_map, nullptr,
   2032           HObjectAccess::ForMapInObjectPropertiesOrConstructorFunctionIndex());
   2033 
   2034       // Check if {receiver} has a constructor (null and undefined have no
   2035       // constructors, so we deoptimize to the runtime to throw an exception).
   2036       IfBuilder constructor_function_index_is_invalid(this);
   2037       constructor_function_index_is_invalid.If<HCompareNumericAndBranch>(
   2038           constructor_function_index,
   2039           Add<HConstant>(Map::kNoConstructorFunctionIndex), Token::EQ);
   2040       constructor_function_index_is_invalid.ThenDeopt(
   2041           DeoptimizeReason::kUndefinedOrNullInToObject);
   2042       constructor_function_index_is_invalid.End();
   2043 
   2044       // Use the global constructor function.
   2045       Push(constructor_function_index);
   2046     }
   2047     receiver_is_not_spec_object.JoinContinuation(&wrap);
   2048   }
   2049   receiver_is_smi.JoinContinuation(&wrap);
   2050 
   2051   // Wrap the receiver if necessary.
   2052   IfBuilder if_wrap(this, &wrap);
   2053   if_wrap.Then();
   2054   {
   2055     // Grab the constructor function index.
   2056     HValue* constructor_index = Pop();
   2057 
   2058     // Load native context.
   2059     HValue* native_context = BuildGetNativeContext();
   2060 
   2061     // Determine the initial map for the global constructor.
   2062     HValue* constructor = Add<HLoadKeyed>(native_context, constructor_index,
   2063                                           nullptr, nullptr, FAST_ELEMENTS);
   2064     HValue* constructor_initial_map = Add<HLoadNamedField>(
   2065         constructor, nullptr, HObjectAccess::ForPrototypeOrInitialMap());
   2066     // Allocate and initialize a JSValue wrapper.
   2067     HValue* value =
   2068         BuildAllocate(Add<HConstant>(JSValue::kSize), HType::JSObject(),
   2069                       JS_VALUE_TYPE, HAllocationMode());
   2070     Add<HStoreNamedField>(value, HObjectAccess::ForMap(),
   2071                           constructor_initial_map);
   2072     HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
   2073     Add<HStoreNamedField>(value, HObjectAccess::ForPropertiesPointer(),
   2074                           empty_fixed_array);
   2075     Add<HStoreNamedField>(value, HObjectAccess::ForElementsPointer(),
   2076                           empty_fixed_array);
   2077     Add<HStoreNamedField>(value, HObjectAccess::ForObservableJSObjectOffset(
   2078                                      JSValue::kValueOffset),
   2079                           receiver);
   2080     Push(value);
   2081   }
   2082   if_wrap.Else();
   2083   { Push(receiver); }
   2084   if_wrap.End();
   2085   return Pop();
   2086 }
   2087 
   2088 
   2089 HAllocate* HGraphBuilder::BuildAllocate(
   2090     HValue* object_size,
   2091     HType type,
   2092     InstanceType instance_type,
   2093     HAllocationMode allocation_mode) {
   2094   // Compute the effective allocation size.
   2095   HValue* size = object_size;
   2096   if (allocation_mode.CreateAllocationMementos()) {
   2097     size = AddUncasted<HAdd>(size, Add<HConstant>(AllocationMemento::kSize));
   2098     size->ClearFlag(HValue::kCanOverflow);
   2099   }
   2100 
   2101   // Perform the actual allocation.
   2102   HAllocate* object = Add<HAllocate>(
   2103       size, type, allocation_mode.GetPretenureMode(), instance_type,
   2104       graph()->GetConstant0(), allocation_mode.feedback_site());
   2105 
   2106   // Setup the allocation memento.
   2107   if (allocation_mode.CreateAllocationMementos()) {
   2108     BuildCreateAllocationMemento(
   2109         object, object_size, allocation_mode.current_site());
   2110   }
   2111 
   2112   return object;
   2113 }
   2114 
   2115 
   2116 HValue* HGraphBuilder::BuildAddStringLengths(HValue* left_length,
   2117                                              HValue* right_length) {
   2118   // Compute the combined string length and check against max string length.
   2119   HValue* length = AddUncasted<HAdd>(left_length, right_length);
   2120   // Check that length <= kMaxLength <=> length < MaxLength + 1.
   2121   HValue* max_length = Add<HConstant>(String::kMaxLength + 1);
   2122   if (top_info()->IsStub() || !isolate()->IsStringLengthOverflowIntact()) {
   2123     // This is a mitigation for crbug.com/627934; the real fix
   2124     // will be to migrate the StringAddStub to TurboFan one day.
   2125     IfBuilder if_invalid(this);
   2126     if_invalid.If<HCompareNumericAndBranch>(length, max_length, Token::GT);
   2127     if_invalid.Then();
   2128     {
   2129       Add<HCallRuntime>(
   2130           Runtime::FunctionForId(Runtime::kThrowInvalidStringLength), 0);
   2131     }
   2132     if_invalid.End();
   2133   } else {
   2134     graph()->MarkDependsOnStringLengthOverflow();
   2135     Add<HBoundsCheck>(length, max_length);
   2136   }
   2137   return length;
   2138 }
   2139 
   2140 
   2141 HValue* HGraphBuilder::BuildCreateConsString(
   2142     HValue* length,
   2143     HValue* left,
   2144     HValue* right,
   2145     HAllocationMode allocation_mode) {
   2146   // Determine the string instance types.
   2147   HInstruction* left_instance_type = AddLoadStringInstanceType(left);
   2148   HInstruction* right_instance_type = AddLoadStringInstanceType(right);
   2149 
   2150   // Allocate the cons string object. HAllocate does not care whether we
   2151   // pass CONS_STRING_TYPE or CONS_ONE_BYTE_STRING_TYPE here, so we just use
   2152   // CONS_STRING_TYPE here. Below we decide whether the cons string is
   2153   // one-byte or two-byte and set the appropriate map.
   2154   DCHECK(HAllocate::CompatibleInstanceTypes(CONS_STRING_TYPE,
   2155                                             CONS_ONE_BYTE_STRING_TYPE));
   2156   HAllocate* result = BuildAllocate(Add<HConstant>(ConsString::kSize),
   2157                                     HType::String(), CONS_STRING_TYPE,
   2158                                     allocation_mode);
   2159 
   2160   // Compute intersection and difference of instance types.
   2161   HValue* anded_instance_types = AddUncasted<HBitwise>(
   2162       Token::BIT_AND, left_instance_type, right_instance_type);
   2163   HValue* xored_instance_types = AddUncasted<HBitwise>(
   2164       Token::BIT_XOR, left_instance_type, right_instance_type);
   2165 
   2166   // We create a one-byte cons string if
   2167   // 1. both strings are one-byte, or
   2168   // 2. at least one of the strings is two-byte, but happens to contain only
   2169   //    one-byte characters.
   2170   // To do this, we check
   2171   // 1. if both strings are one-byte, or if the one-byte data hint is set in
   2172   //    both strings, or
   2173   // 2. if one of the strings has the one-byte data hint set and the other
   2174   //    string is one-byte.
   2175   IfBuilder if_onebyte(this);
   2176   STATIC_ASSERT(kOneByteStringTag != 0);
   2177   STATIC_ASSERT(kOneByteDataHintMask != 0);
   2178   if_onebyte.If<HCompareNumericAndBranch>(
   2179       AddUncasted<HBitwise>(
   2180           Token::BIT_AND, anded_instance_types,
   2181           Add<HConstant>(static_cast<int32_t>(
   2182                   kStringEncodingMask | kOneByteDataHintMask))),
   2183       graph()->GetConstant0(), Token::NE);
   2184   if_onebyte.Or();
   2185   STATIC_ASSERT(kOneByteStringTag != 0 &&
   2186                 kOneByteDataHintTag != 0 &&
   2187                 kOneByteDataHintTag != kOneByteStringTag);
   2188   if_onebyte.If<HCompareNumericAndBranch>(
   2189       AddUncasted<HBitwise>(
   2190           Token::BIT_AND, xored_instance_types,
   2191           Add<HConstant>(static_cast<int32_t>(
   2192                   kOneByteStringTag | kOneByteDataHintTag))),
   2193       Add<HConstant>(static_cast<int32_t>(
   2194               kOneByteStringTag | kOneByteDataHintTag)), Token::EQ);
   2195   if_onebyte.Then();
   2196   {
   2197     // We can safely skip the write barrier for storing the map here.
   2198     Add<HStoreNamedField>(
   2199         result, HObjectAccess::ForMap(),
   2200         Add<HConstant>(isolate()->factory()->cons_one_byte_string_map()));
   2201   }
   2202   if_onebyte.Else();
   2203   {
   2204     // We can safely skip the write barrier for storing the map here.
   2205     Add<HStoreNamedField>(
   2206         result, HObjectAccess::ForMap(),
   2207         Add<HConstant>(isolate()->factory()->cons_string_map()));
   2208   }
   2209   if_onebyte.End();
   2210 
   2211   // Initialize the cons string fields.
   2212   Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
   2213                         Add<HConstant>(String::kEmptyHashField));
   2214   Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
   2215   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringFirst(), left);
   2216   Add<HStoreNamedField>(result, HObjectAccess::ForConsStringSecond(), right);
   2217 
   2218   // Count the native string addition.
   2219   AddIncrementCounter(isolate()->counters()->string_add_native());
   2220 
   2221   return result;
   2222 }
   2223 
   2224 
   2225 void HGraphBuilder::BuildCopySeqStringChars(HValue* src,
   2226                                             HValue* src_offset,
   2227                                             String::Encoding src_encoding,
   2228                                             HValue* dst,
   2229                                             HValue* dst_offset,
   2230                                             String::Encoding dst_encoding,
   2231                                             HValue* length) {
   2232   DCHECK(dst_encoding != String::ONE_BYTE_ENCODING ||
   2233          src_encoding == String::ONE_BYTE_ENCODING);
   2234   LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
   2235   HValue* index = loop.BeginBody(graph()->GetConstant0(), length, Token::LT);
   2236   {
   2237     HValue* src_index = AddUncasted<HAdd>(src_offset, index);
   2238     HValue* value =
   2239         AddUncasted<HSeqStringGetChar>(src_encoding, src, src_index);
   2240     HValue* dst_index = AddUncasted<HAdd>(dst_offset, index);
   2241     Add<HSeqStringSetChar>(dst_encoding, dst, dst_index, value);
   2242   }
   2243   loop.EndBody();
   2244 }
   2245 
   2246 
   2247 HValue* HGraphBuilder::BuildObjectSizeAlignment(
   2248     HValue* unaligned_size, int header_size) {
   2249   DCHECK((header_size & kObjectAlignmentMask) == 0);
   2250   HValue* size = AddUncasted<HAdd>(
   2251       unaligned_size, Add<HConstant>(static_cast<int32_t>(
   2252           header_size + kObjectAlignmentMask)));
   2253   size->ClearFlag(HValue::kCanOverflow);
   2254   return AddUncasted<HBitwise>(
   2255       Token::BIT_AND, size, Add<HConstant>(static_cast<int32_t>(
   2256           ~kObjectAlignmentMask)));
   2257 }
   2258 
   2259 
   2260 HValue* HGraphBuilder::BuildUncheckedStringAdd(
   2261     HValue* left,
   2262     HValue* right,
   2263     HAllocationMode allocation_mode) {
   2264   // Determine the string lengths.
   2265   HValue* left_length = AddLoadStringLength(left);
   2266   HValue* right_length = AddLoadStringLength(right);
   2267 
   2268   // Compute the combined string length.
   2269   HValue* length = BuildAddStringLengths(left_length, right_length);
   2270 
   2271   // Do some manual constant folding here.
   2272   if (left_length->IsConstant()) {
   2273     HConstant* c_left_length = HConstant::cast(left_length);
   2274     DCHECK_NE(0, c_left_length->Integer32Value());
   2275     if (c_left_length->Integer32Value() + 1 >= ConsString::kMinLength) {
   2276       // The right string contains at least one character.
   2277       return BuildCreateConsString(length, left, right, allocation_mode);
   2278     }
   2279   } else if (right_length->IsConstant()) {
   2280     HConstant* c_right_length = HConstant::cast(right_length);
   2281     DCHECK_NE(0, c_right_length->Integer32Value());
   2282     if (c_right_length->Integer32Value() + 1 >= ConsString::kMinLength) {
   2283       // The left string contains at least one character.
   2284       return BuildCreateConsString(length, left, right, allocation_mode);
   2285     }
   2286   }
   2287 
   2288   // Check if we should create a cons string.
   2289   IfBuilder if_createcons(this);
   2290   if_createcons.If<HCompareNumericAndBranch>(
   2291       length, Add<HConstant>(ConsString::kMinLength), Token::GTE);
   2292   if_createcons.Then();
   2293   {
   2294     // Create a cons string.
   2295     Push(BuildCreateConsString(length, left, right, allocation_mode));
   2296   }
   2297   if_createcons.Else();
   2298   {
   2299     // Determine the string instance types.
   2300     HValue* left_instance_type = AddLoadStringInstanceType(left);
   2301     HValue* right_instance_type = AddLoadStringInstanceType(right);
   2302 
   2303     // Compute union and difference of instance types.
   2304     HValue* ored_instance_types = AddUncasted<HBitwise>(
   2305         Token::BIT_OR, left_instance_type, right_instance_type);
   2306     HValue* xored_instance_types = AddUncasted<HBitwise>(
   2307         Token::BIT_XOR, left_instance_type, right_instance_type);
   2308 
   2309     // Check if both strings have the same encoding and both are
   2310     // sequential.
   2311     IfBuilder if_sameencodingandsequential(this);
   2312     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
   2313         AddUncasted<HBitwise>(
   2314             Token::BIT_AND, xored_instance_types,
   2315             Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
   2316         graph()->GetConstant0(), Token::EQ);
   2317     if_sameencodingandsequential.And();
   2318     STATIC_ASSERT(kSeqStringTag == 0);
   2319     if_sameencodingandsequential.If<HCompareNumericAndBranch>(
   2320         AddUncasted<HBitwise>(
   2321             Token::BIT_AND, ored_instance_types,
   2322             Add<HConstant>(static_cast<int32_t>(kStringRepresentationMask))),
   2323         graph()->GetConstant0(), Token::EQ);
   2324     if_sameencodingandsequential.Then();
   2325     {
   2326       HConstant* string_map =
   2327           Add<HConstant>(isolate()->factory()->string_map());
   2328       HConstant* one_byte_string_map =
   2329           Add<HConstant>(isolate()->factory()->one_byte_string_map());
   2330 
   2331       // Determine map and size depending on whether result is one-byte string.
   2332       IfBuilder if_onebyte(this);
   2333       STATIC_ASSERT(kOneByteStringTag != 0);
   2334       if_onebyte.If<HCompareNumericAndBranch>(
   2335           AddUncasted<HBitwise>(
   2336               Token::BIT_AND, ored_instance_types,
   2337               Add<HConstant>(static_cast<int32_t>(kStringEncodingMask))),
   2338           graph()->GetConstant0(), Token::NE);
   2339       if_onebyte.Then();
   2340       {
   2341         // Allocate sequential one-byte string object.
   2342         Push(length);
   2343         Push(one_byte_string_map);
   2344       }
   2345       if_onebyte.Else();
   2346       {
   2347         // Allocate sequential two-byte string object.
   2348         HValue* size = AddUncasted<HShl>(length, graph()->GetConstant1());
   2349         size->ClearFlag(HValue::kCanOverflow);
   2350         size->SetFlag(HValue::kUint32);
   2351         Push(size);
   2352         Push(string_map);
   2353       }
   2354       if_onebyte.End();
   2355       HValue* map = Pop();
   2356 
   2357       // Calculate the number of bytes needed for the characters in the
   2358       // string while observing object alignment.
   2359       STATIC_ASSERT((SeqString::kHeaderSize & kObjectAlignmentMask) == 0);
   2360       HValue* size = BuildObjectSizeAlignment(Pop(), SeqString::kHeaderSize);
   2361 
   2362       IfBuilder if_size(this);
   2363       if_size.If<HCompareNumericAndBranch>(
   2364           size, Add<HConstant>(kMaxRegularHeapObjectSize), Token::LT);
   2365       if_size.Then();
   2366       {
   2367         // Allocate the string object. HAllocate does not care whether we pass
   2368         // STRING_TYPE or ONE_BYTE_STRING_TYPE here, so we just use STRING_TYPE.
   2369         HAllocate* result =
   2370             BuildAllocate(size, HType::String(), STRING_TYPE, allocation_mode);
   2371         Add<HStoreNamedField>(result, HObjectAccess::ForMap(), map);
   2372 
   2373         // Initialize the string fields.
   2374         Add<HStoreNamedField>(result, HObjectAccess::ForStringHashField(),
   2375                               Add<HConstant>(String::kEmptyHashField));
   2376         Add<HStoreNamedField>(result, HObjectAccess::ForStringLength(), length);
   2377 
   2378         // Copy characters to the result string.
   2379         IfBuilder if_twobyte(this);
   2380         if_twobyte.If<HCompareObjectEqAndBranch>(map, string_map);
   2381         if_twobyte.Then();
   2382         {
   2383           // Copy characters from the left string.
   2384           BuildCopySeqStringChars(
   2385               left, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, result,
   2386               graph()->GetConstant0(), String::TWO_BYTE_ENCODING, left_length);
   2387 
   2388           // Copy characters from the right string.
   2389           BuildCopySeqStringChars(
   2390               right, graph()->GetConstant0(), String::TWO_BYTE_ENCODING, result,
   2391               left_length, String::TWO_BYTE_ENCODING, right_length);
   2392         }
   2393         if_twobyte.Else();
   2394         {
   2395           // Copy characters from the left string.
   2396           BuildCopySeqStringChars(
   2397               left, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, result,
   2398               graph()->GetConstant0(), String::ONE_BYTE_ENCODING, left_length);
   2399 
   2400           // Copy characters from the right string.
   2401           BuildCopySeqStringChars(
   2402               right, graph()->GetConstant0(), String::ONE_BYTE_ENCODING, result,
   2403               left_length, String::ONE_BYTE_ENCODING, right_length);
   2404         }
   2405         if_twobyte.End();
   2406 
   2407         // Count the native string addition.
   2408         AddIncrementCounter(isolate()->counters()->string_add_native());
   2409 
   2410         // Return the sequential string.
   2411         Push(result);
   2412       }
   2413       if_size.Else();
   2414       {
   2415         // Fallback to the runtime to add the two strings. The string has to be
   2416         // allocated in LO space.
   2417         Add<HPushArguments>(left, right);
   2418         Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
   2419       }
   2420       if_size.End();
   2421     }
   2422     if_sameencodingandsequential.Else();
   2423     {
   2424       // Fallback to the runtime to add the two strings.
   2425       Add<HPushArguments>(left, right);
   2426       Push(Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kStringAdd), 2));
   2427     }
   2428     if_sameencodingandsequential.End();
   2429   }
   2430   if_createcons.End();
   2431 
   2432   return Pop();
   2433 }
   2434 
   2435 
   2436 HValue* HGraphBuilder::BuildStringAdd(
   2437     HValue* left,
   2438     HValue* right,
   2439     HAllocationMode allocation_mode) {
   2440   NoObservableSideEffectsScope no_effects(this);
   2441 
   2442   // Determine string lengths.
   2443   HValue* left_length = AddLoadStringLength(left);
   2444   HValue* right_length = AddLoadStringLength(right);
   2445 
   2446   // Check if left string is empty.
   2447   IfBuilder if_leftempty(this);
   2448   if_leftempty.If<HCompareNumericAndBranch>(
   2449       left_length, graph()->GetConstant0(), Token::EQ);
   2450   if_leftempty.Then();
   2451   {
   2452     // Count the native string addition.
   2453     AddIncrementCounter(isolate()->counters()->string_add_native());
   2454 
   2455     // Just return the right string.
   2456     Push(right);
   2457   }
   2458   if_leftempty.Else();
   2459   {
   2460     // Check if right string is empty.
   2461     IfBuilder if_rightempty(this);
   2462     if_rightempty.If<HCompareNumericAndBranch>(
   2463         right_length, graph()->GetConstant0(), Token::EQ);
   2464     if_rightempty.Then();
   2465     {
   2466       // Count the native string addition.
   2467       AddIncrementCounter(isolate()->counters()->string_add_native());
   2468 
   2469       // Just return the left string.
   2470       Push(left);
   2471     }
   2472     if_rightempty.Else();
   2473     {
   2474       // Add the two non-empty strings.
   2475       Push(BuildUncheckedStringAdd(left, right, allocation_mode));
   2476     }
   2477     if_rightempty.End();
   2478   }
   2479   if_leftempty.End();
   2480 
   2481   return Pop();
   2482 }
   2483 
   2484 
   2485 HInstruction* HGraphBuilder::BuildUncheckedMonomorphicElementAccess(
   2486     HValue* checked_object,
   2487     HValue* key,
   2488     HValue* val,
   2489     bool is_js_array,
   2490     ElementsKind elements_kind,
   2491     PropertyAccessType access_type,
   2492     LoadKeyedHoleMode load_mode,
   2493     KeyedAccessStoreMode store_mode) {
   2494   DCHECK(top_info()->IsStub() || checked_object->IsCompareMap() ||
   2495          checked_object->IsCheckMaps());
   2496   DCHECK(!IsFixedTypedArrayElementsKind(elements_kind) || !is_js_array);
   2497   // No GVNFlag is necessary for ElementsKind if there is an explicit dependency
   2498   // on a HElementsTransition instruction. The flag can also be removed if the
   2499   // map to check has FAST_HOLEY_ELEMENTS, since there can be no further
   2500   // ElementsKind transitions. Finally, the dependency can be removed for stores
   2501   // for FAST_ELEMENTS, since a transition to HOLEY elements won't change the
   2502   // generated store code.
   2503   if ((elements_kind == FAST_HOLEY_ELEMENTS) ||
   2504       (elements_kind == FAST_ELEMENTS && access_type == STORE)) {
   2505     checked_object->ClearDependsOnFlag(kElementsKind);
   2506   }
   2507 
   2508   bool fast_smi_only_elements = IsFastSmiElementsKind(elements_kind);
   2509   bool fast_elements = IsFastObjectElementsKind(elements_kind);
   2510   HValue* elements = AddLoadElements(checked_object);
   2511   if (access_type == STORE && (fast_elements || fast_smi_only_elements) &&
   2512       store_mode != STORE_NO_TRANSITION_HANDLE_COW) {
   2513     HCheckMaps* check_cow_map = Add<HCheckMaps>(
   2514         elements, isolate()->factory()->fixed_array_map());
   2515     check_cow_map->ClearDependsOnFlag(kElementsKind);
   2516   }
   2517   HInstruction* length = NULL;
   2518   if (is_js_array) {
   2519     length = Add<HLoadNamedField>(
   2520         checked_object->ActualValue(), checked_object,
   2521         HObjectAccess::ForArrayLength(elements_kind));
   2522   } else {
   2523     length = AddLoadFixedArrayLength(elements);
   2524   }
   2525   length->set_type(HType::Smi());
   2526   HValue* checked_key = NULL;
   2527   if (IsFixedTypedArrayElementsKind(elements_kind)) {
   2528     checked_object = Add<HCheckArrayBufferNotNeutered>(checked_object);
   2529 
   2530     HValue* external_pointer = Add<HLoadNamedField>(
   2531         elements, nullptr,
   2532         HObjectAccess::ForFixedTypedArrayBaseExternalPointer());
   2533     HValue* base_pointer = Add<HLoadNamedField>(
   2534         elements, nullptr, HObjectAccess::ForFixedTypedArrayBaseBasePointer());
   2535     HValue* backing_store = AddUncasted<HAdd>(external_pointer, base_pointer,
   2536                                               AddOfExternalAndTagged);
   2537 
   2538     if (store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS) {
   2539       NoObservableSideEffectsScope no_effects(this);
   2540       IfBuilder length_checker(this);
   2541       length_checker.If<HCompareNumericAndBranch>(key, length, Token::LT);
   2542       length_checker.Then();
   2543       IfBuilder negative_checker(this);
   2544       HValue* bounds_check = negative_checker.If<HCompareNumericAndBranch>(
   2545           key, graph()->GetConstant0(), Token::GTE);
   2546       negative_checker.Then();
   2547       HInstruction* result = AddElementAccess(
   2548           backing_store, key, val, bounds_check, checked_object->ActualValue(),
   2549           elements_kind, access_type);
   2550       negative_checker.ElseDeopt(DeoptimizeReason::kNegativeKeyEncountered);
   2551       negative_checker.End();
   2552       length_checker.End();
   2553       return result;
   2554     } else {
   2555       DCHECK(store_mode == STANDARD_STORE);
   2556       checked_key = Add<HBoundsCheck>(key, length);
   2557       return AddElementAccess(backing_store, checked_key, val, checked_object,
   2558                               checked_object->ActualValue(), elements_kind,
   2559                               access_type);
   2560     }
   2561   }
   2562   DCHECK(fast_smi_only_elements ||
   2563          fast_elements ||
   2564          IsFastDoubleElementsKind(elements_kind));
   2565 
   2566   // In case val is stored into a fast smi array, assure that the value is a smi
   2567   // before manipulating the backing store. Otherwise the actual store may
   2568   // deopt, leaving the backing store in an invalid state.
   2569   if (access_type == STORE && IsFastSmiElementsKind(elements_kind) &&
   2570       !val->type().IsSmi()) {
   2571     val = AddUncasted<HForceRepresentation>(val, Representation::Smi());
   2572   }
   2573 
   2574   if (IsGrowStoreMode(store_mode)) {
   2575     NoObservableSideEffectsScope no_effects(this);
   2576     Representation representation = HStoreKeyed::RequiredValueRepresentation(
   2577         elements_kind, STORE_TO_INITIALIZED_ENTRY);
   2578     val = AddUncasted<HForceRepresentation>(val, representation);
   2579     elements = BuildCheckForCapacityGrow(checked_object, elements,
   2580                                          elements_kind, length, key,
   2581                                          is_js_array, access_type);
   2582     checked_key = key;
   2583   } else {
   2584     checked_key = Add<HBoundsCheck>(key, length);
   2585 
   2586     if (access_type == STORE && (fast_elements || fast_smi_only_elements)) {
   2587       if (store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
   2588         NoObservableSideEffectsScope no_effects(this);
   2589         elements = BuildCopyElementsOnWrite(checked_object, elements,
   2590                                             elements_kind, length);
   2591       } else {
   2592         HCheckMaps* check_cow_map = Add<HCheckMaps>(
   2593             elements, isolate()->factory()->fixed_array_map());
   2594         check_cow_map->ClearDependsOnFlag(kElementsKind);
   2595       }
   2596     }
   2597   }
   2598   return AddElementAccess(elements, checked_key, val, checked_object, nullptr,
   2599                           elements_kind, access_type, load_mode);
   2600 }
   2601 
   2602 
   2603 HValue* HGraphBuilder::BuildCalculateElementsSize(ElementsKind kind,
   2604                                                   HValue* capacity) {
   2605   int elements_size = IsFastDoubleElementsKind(kind)
   2606       ? kDoubleSize
   2607       : kPointerSize;
   2608 
   2609   HConstant* elements_size_value = Add<HConstant>(elements_size);
   2610   HInstruction* mul =
   2611       HMul::NewImul(isolate(), zone(), context(), capacity->ActualValue(),
   2612                     elements_size_value);
   2613   AddInstruction(mul);
   2614   mul->ClearFlag(HValue::kCanOverflow);
   2615 
   2616   STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
   2617 
   2618   HConstant* header_size = Add<HConstant>(FixedArray::kHeaderSize);
   2619   HValue* total_size = AddUncasted<HAdd>(mul, header_size);
   2620   total_size->ClearFlag(HValue::kCanOverflow);
   2621   return total_size;
   2622 }
   2623 
   2624 
   2625 HAllocate* HGraphBuilder::AllocateJSArrayObject(AllocationSiteMode mode) {
   2626   int base_size = JSArray::kSize;
   2627   if (mode == TRACK_ALLOCATION_SITE) {
   2628     base_size += AllocationMemento::kSize;
   2629   }
   2630   HConstant* size_in_bytes = Add<HConstant>(base_size);
   2631   return Add<HAllocate>(size_in_bytes, HType::JSArray(), NOT_TENURED,
   2632                         JS_OBJECT_TYPE, graph()->GetConstant0());
   2633 }
   2634 
   2635 
   2636 HConstant* HGraphBuilder::EstablishElementsAllocationSize(
   2637     ElementsKind kind,
   2638     int capacity) {
   2639   int base_size = IsFastDoubleElementsKind(kind)
   2640       ? FixedDoubleArray::SizeFor(capacity)
   2641       : FixedArray::SizeFor(capacity);
   2642 
   2643   return Add<HConstant>(base_size);
   2644 }
   2645 
   2646 
   2647 HAllocate* HGraphBuilder::BuildAllocateElements(ElementsKind kind,
   2648                                                 HValue* size_in_bytes) {
   2649   InstanceType instance_type = IsFastDoubleElementsKind(kind)
   2650       ? FIXED_DOUBLE_ARRAY_TYPE
   2651       : FIXED_ARRAY_TYPE;
   2652 
   2653   return Add<HAllocate>(size_in_bytes, HType::HeapObject(), NOT_TENURED,
   2654                         instance_type, graph()->GetConstant0());
   2655 }
   2656 
   2657 
   2658 void HGraphBuilder::BuildInitializeElementsHeader(HValue* elements,
   2659                                                   ElementsKind kind,
   2660                                                   HValue* capacity) {
   2661   Factory* factory = isolate()->factory();
   2662   Handle<Map> map = IsFastDoubleElementsKind(kind)
   2663       ? factory->fixed_double_array_map()
   2664       : factory->fixed_array_map();
   2665 
   2666   Add<HStoreNamedField>(elements, HObjectAccess::ForMap(), Add<HConstant>(map));
   2667   Add<HStoreNamedField>(elements, HObjectAccess::ForFixedArrayLength(),
   2668                         capacity);
   2669 }
   2670 
   2671 
   2672 HValue* HGraphBuilder::BuildAllocateAndInitializeArray(ElementsKind kind,
   2673                                                        HValue* capacity) {
   2674   // The HForceRepresentation is to prevent possible deopt on int-smi
   2675   // conversion after allocation but before the new object fields are set.
   2676   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
   2677   HValue* size_in_bytes = BuildCalculateElementsSize(kind, capacity);
   2678   HValue* new_array = BuildAllocateElements(kind, size_in_bytes);
   2679   BuildInitializeElementsHeader(new_array, kind, capacity);
   2680   return new_array;
   2681 }
   2682 
   2683 
   2684 void HGraphBuilder::BuildJSArrayHeader(HValue* array,
   2685                                        HValue* array_map,
   2686                                        HValue* elements,
   2687                                        AllocationSiteMode mode,
   2688                                        ElementsKind elements_kind,
   2689                                        HValue* allocation_site_payload,
   2690                                        HValue* length_field) {
   2691   Add<HStoreNamedField>(array, HObjectAccess::ForMap(), array_map);
   2692 
   2693   HValue* empty_fixed_array = Add<HLoadRoot>(Heap::kEmptyFixedArrayRootIndex);
   2694 
   2695   Add<HStoreNamedField>(
   2696       array, HObjectAccess::ForPropertiesPointer(), empty_fixed_array);
   2697 
   2698   Add<HStoreNamedField>(array, HObjectAccess::ForElementsPointer(),
   2699                         elements != nullptr ? elements : empty_fixed_array);
   2700 
   2701   Add<HStoreNamedField>(
   2702       array, HObjectAccess::ForArrayLength(elements_kind), length_field);
   2703 
   2704   if (mode == TRACK_ALLOCATION_SITE) {
   2705     BuildCreateAllocationMemento(
   2706         array, Add<HConstant>(JSArray::kSize), allocation_site_payload);
   2707   }
   2708 }
   2709 
   2710 
   2711 HInstruction* HGraphBuilder::AddElementAccess(
   2712     HValue* elements, HValue* checked_key, HValue* val, HValue* dependency,
   2713     HValue* backing_store_owner, ElementsKind elements_kind,
   2714     PropertyAccessType access_type, LoadKeyedHoleMode load_mode) {
   2715   if (access_type == STORE) {
   2716     DCHECK(val != NULL);
   2717     if (elements_kind == UINT8_CLAMPED_ELEMENTS) {
   2718       val = Add<HClampToUint8>(val);
   2719     }
   2720     return Add<HStoreKeyed>(elements, checked_key, val, backing_store_owner,
   2721                             elements_kind, STORE_TO_INITIALIZED_ENTRY);
   2722   }
   2723 
   2724   DCHECK(access_type == LOAD);
   2725   DCHECK(val == NULL);
   2726   HLoadKeyed* load =
   2727       Add<HLoadKeyed>(elements, checked_key, dependency, backing_store_owner,
   2728                       elements_kind, load_mode);
   2729   if (elements_kind == UINT32_ELEMENTS) {
   2730     graph()->RecordUint32Instruction(load);
   2731   }
   2732   return load;
   2733 }
   2734 
   2735 
   2736 HLoadNamedField* HGraphBuilder::AddLoadMap(HValue* object,
   2737                                            HValue* dependency) {
   2738   return Add<HLoadNamedField>(object, dependency, HObjectAccess::ForMap());
   2739 }
   2740 
   2741 
   2742 HLoadNamedField* HGraphBuilder::AddLoadElements(HValue* object,
   2743                                                 HValue* dependency) {
   2744   return Add<HLoadNamedField>(
   2745       object, dependency, HObjectAccess::ForElementsPointer());
   2746 }
   2747 
   2748 
   2749 HLoadNamedField* HGraphBuilder::AddLoadFixedArrayLength(
   2750     HValue* array,
   2751     HValue* dependency) {
   2752   return Add<HLoadNamedField>(
   2753       array, dependency, HObjectAccess::ForFixedArrayLength());
   2754 }
   2755 
   2756 
   2757 HLoadNamedField* HGraphBuilder::AddLoadArrayLength(HValue* array,
   2758                                                    ElementsKind kind,
   2759                                                    HValue* dependency) {
   2760   return Add<HLoadNamedField>(
   2761       array, dependency, HObjectAccess::ForArrayLength(kind));
   2762 }
   2763 
   2764 
   2765 HValue* HGraphBuilder::BuildNewElementsCapacity(HValue* old_capacity) {
   2766   HValue* half_old_capacity = AddUncasted<HShr>(old_capacity,
   2767                                                 graph_->GetConstant1());
   2768 
   2769   HValue* new_capacity = AddUncasted<HAdd>(half_old_capacity, old_capacity);
   2770   new_capacity->ClearFlag(HValue::kCanOverflow);
   2771 
   2772   HValue* min_growth = Add<HConstant>(16);
   2773 
   2774   new_capacity = AddUncasted<HAdd>(new_capacity, min_growth);
   2775   new_capacity->ClearFlag(HValue::kCanOverflow);
   2776 
   2777   return new_capacity;
   2778 }
   2779 
   2780 
   2781 HValue* HGraphBuilder::BuildGrowElementsCapacity(HValue* object,
   2782                                                  HValue* elements,
   2783                                                  ElementsKind kind,
   2784                                                  ElementsKind new_kind,
   2785                                                  HValue* length,
   2786                                                  HValue* new_capacity) {
   2787   Add<HBoundsCheck>(
   2788       new_capacity,
   2789       Add<HConstant>((kMaxRegularHeapObjectSize - FixedArray::kHeaderSize) >>
   2790                      ElementsKindToShiftSize(new_kind)));
   2791 
   2792   HValue* new_elements =
   2793       BuildAllocateAndInitializeArray(new_kind, new_capacity);
   2794 
   2795   BuildCopyElements(elements, kind, new_elements,
   2796                     new_kind, length, new_capacity);
   2797 
   2798   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   2799                         new_elements);
   2800 
   2801   return new_elements;
   2802 }
   2803 
   2804 
   2805 void HGraphBuilder::BuildFillElementsWithValue(HValue* elements,
   2806                                                ElementsKind elements_kind,
   2807                                                HValue* from,
   2808                                                HValue* to,
   2809                                                HValue* value) {
   2810   if (to == NULL) {
   2811     to = AddLoadFixedArrayLength(elements);
   2812   }
   2813 
   2814   // Special loop unfolding case
   2815   STATIC_ASSERT(JSArray::kPreallocatedArrayElements <=
   2816                 kElementLoopUnrollThreshold);
   2817   int initial_capacity = -1;
   2818   if (from->IsInteger32Constant() && to->IsInteger32Constant()) {
   2819     int constant_from = from->GetInteger32Constant();
   2820     int constant_to = to->GetInteger32Constant();
   2821 
   2822     if (constant_from == 0 && constant_to <= kElementLoopUnrollThreshold) {
   2823       initial_capacity = constant_to;
   2824     }
   2825   }
   2826 
   2827   if (initial_capacity >= 0) {
   2828     for (int i = 0; i < initial_capacity; i++) {
   2829       HInstruction* key = Add<HConstant>(i);
   2830       Add<HStoreKeyed>(elements, key, value, nullptr, elements_kind);
   2831     }
   2832   } else {
   2833     // Carefully loop backwards so that the "from" remains live through the loop
   2834     // rather than the to. This often corresponds to keeping length live rather
   2835     // then capacity, which helps register allocation, since length is used more
   2836     // other than capacity after filling with holes.
   2837     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   2838 
   2839     HValue* key = builder.BeginBody(to, from, Token::GT);
   2840 
   2841     HValue* adjusted_key = AddUncasted<HSub>(key, graph()->GetConstant1());
   2842     adjusted_key->ClearFlag(HValue::kCanOverflow);
   2843 
   2844     Add<HStoreKeyed>(elements, adjusted_key, value, nullptr, elements_kind);
   2845 
   2846     builder.EndBody();
   2847   }
   2848 }
   2849 
   2850 
   2851 void HGraphBuilder::BuildFillElementsWithHole(HValue* elements,
   2852                                               ElementsKind elements_kind,
   2853                                               HValue* from,
   2854                                               HValue* to) {
   2855   // Fast elements kinds need to be initialized in case statements below cause a
   2856   // garbage collection.
   2857 
   2858   HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
   2859                      ? graph()->GetConstantHole()
   2860                      : Add<HConstant>(HConstant::kHoleNaN);
   2861 
   2862   // Since we're about to store a hole value, the store instruction below must
   2863   // assume an elements kind that supports heap object values.
   2864   if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   2865     elements_kind = FAST_HOLEY_ELEMENTS;
   2866   }
   2867 
   2868   BuildFillElementsWithValue(elements, elements_kind, from, to, hole);
   2869 }
   2870 
   2871 
   2872 void HGraphBuilder::BuildCopyProperties(HValue* from_properties,
   2873                                         HValue* to_properties, HValue* length,
   2874                                         HValue* capacity) {
   2875   ElementsKind kind = FAST_ELEMENTS;
   2876 
   2877   BuildFillElementsWithValue(to_properties, kind, length, capacity,
   2878                              graph()->GetConstantUndefined());
   2879 
   2880   LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   2881 
   2882   HValue* key = builder.BeginBody(length, graph()->GetConstant0(), Token::GT);
   2883 
   2884   key = AddUncasted<HSub>(key, graph()->GetConstant1());
   2885   key->ClearFlag(HValue::kCanOverflow);
   2886 
   2887   HValue* element =
   2888       Add<HLoadKeyed>(from_properties, key, nullptr, nullptr, kind);
   2889 
   2890   Add<HStoreKeyed>(to_properties, key, element, nullptr, kind);
   2891 
   2892   builder.EndBody();
   2893 }
   2894 
   2895 
   2896 void HGraphBuilder::BuildCopyElements(HValue* from_elements,
   2897                                       ElementsKind from_elements_kind,
   2898                                       HValue* to_elements,
   2899                                       ElementsKind to_elements_kind,
   2900                                       HValue* length,
   2901                                       HValue* capacity) {
   2902   int constant_capacity = -1;
   2903   if (capacity != NULL &&
   2904       capacity->IsConstant() &&
   2905       HConstant::cast(capacity)->HasInteger32Value()) {
   2906     int constant_candidate = HConstant::cast(capacity)->Integer32Value();
   2907     if (constant_candidate <= kElementLoopUnrollThreshold) {
   2908       constant_capacity = constant_candidate;
   2909     }
   2910   }
   2911 
   2912   bool pre_fill_with_holes =
   2913     IsFastDoubleElementsKind(from_elements_kind) &&
   2914     IsFastObjectElementsKind(to_elements_kind);
   2915   if (pre_fill_with_holes) {
   2916     // If the copy might trigger a GC, make sure that the FixedArray is
   2917     // pre-initialized with holes to make sure that it's always in a
   2918     // consistent state.
   2919     BuildFillElementsWithHole(to_elements, to_elements_kind,
   2920                               graph()->GetConstant0(), NULL);
   2921   }
   2922 
   2923   if (constant_capacity != -1) {
   2924     // Unroll the loop for small elements kinds.
   2925     for (int i = 0; i < constant_capacity; i++) {
   2926       HValue* key_constant = Add<HConstant>(i);
   2927       HInstruction* value = Add<HLoadKeyed>(
   2928           from_elements, key_constant, nullptr, nullptr, from_elements_kind);
   2929       Add<HStoreKeyed>(to_elements, key_constant, value, nullptr,
   2930                        to_elements_kind);
   2931     }
   2932   } else {
   2933     if (!pre_fill_with_holes &&
   2934         (capacity == NULL || !length->Equals(capacity))) {
   2935       BuildFillElementsWithHole(to_elements, to_elements_kind,
   2936                                 length, NULL);
   2937     }
   2938 
   2939     LoopBuilder builder(this, context(), LoopBuilder::kPostDecrement);
   2940 
   2941     HValue* key = builder.BeginBody(length, graph()->GetConstant0(),
   2942                                     Token::GT);
   2943 
   2944     key = AddUncasted<HSub>(key, graph()->GetConstant1());
   2945     key->ClearFlag(HValue::kCanOverflow);
   2946 
   2947     HValue* element = Add<HLoadKeyed>(from_elements, key, nullptr, nullptr,
   2948                                       from_elements_kind, ALLOW_RETURN_HOLE);
   2949 
   2950     ElementsKind kind = (IsHoleyElementsKind(from_elements_kind) &&
   2951                          IsFastSmiElementsKind(to_elements_kind))
   2952       ? FAST_HOLEY_ELEMENTS : to_elements_kind;
   2953 
   2954     if (IsHoleyElementsKind(from_elements_kind) &&
   2955         from_elements_kind != to_elements_kind) {
   2956       IfBuilder if_hole(this);
   2957       if_hole.If<HCompareHoleAndBranch>(element);
   2958       if_hole.Then();
   2959       HConstant* hole_constant = IsFastDoubleElementsKind(to_elements_kind)
   2960                                      ? Add<HConstant>(HConstant::kHoleNaN)
   2961                                      : graph()->GetConstantHole();
   2962       Add<HStoreKeyed>(to_elements, key, hole_constant, nullptr, kind);
   2963       if_hole.Else();
   2964       HStoreKeyed* store =
   2965           Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
   2966       store->SetFlag(HValue::kTruncatingToNumber);
   2967       if_hole.End();
   2968     } else {
   2969       HStoreKeyed* store =
   2970           Add<HStoreKeyed>(to_elements, key, element, nullptr, kind);
   2971       store->SetFlag(HValue::kTruncatingToNumber);
   2972     }
   2973 
   2974     builder.EndBody();
   2975   }
   2976 
   2977   Counters* counters = isolate()->counters();
   2978   AddIncrementCounter(counters->inlined_copied_elements());
   2979 }
   2980 
   2981 void HGraphBuilder::BuildCreateAllocationMemento(
   2982     HValue* previous_object,
   2983     HValue* previous_object_size,
   2984     HValue* allocation_site) {
   2985   DCHECK(allocation_site != NULL);
   2986   HInnerAllocatedObject* allocation_memento = Add<HInnerAllocatedObject>(
   2987       previous_object, previous_object_size, HType::HeapObject());
   2988   AddStoreMapConstant(
   2989       allocation_memento, isolate()->factory()->allocation_memento_map());
   2990   Add<HStoreNamedField>(
   2991       allocation_memento,
   2992       HObjectAccess::ForAllocationMementoSite(),
   2993       allocation_site);
   2994   if (FLAG_allocation_site_pretenuring) {
   2995     HValue* memento_create_count =
   2996         Add<HLoadNamedField>(allocation_site, nullptr,
   2997                              HObjectAccess::ForAllocationSiteOffset(
   2998                                  AllocationSite::kPretenureCreateCountOffset));
   2999     memento_create_count = AddUncasted<HAdd>(
   3000         memento_create_count, graph()->GetConstant1());
   3001     // This smi value is reset to zero after every gc, overflow isn't a problem
   3002     // since the counter is bounded by the new space size.
   3003     memento_create_count->ClearFlag(HValue::kCanOverflow);
   3004     Add<HStoreNamedField>(
   3005         allocation_site, HObjectAccess::ForAllocationSiteOffset(
   3006             AllocationSite::kPretenureCreateCountOffset), memento_create_count);
   3007   }
   3008 }
   3009 
   3010 
   3011 HInstruction* HGraphBuilder::BuildGetNativeContext() {
   3012   return Add<HLoadNamedField>(
   3013       context(), nullptr,
   3014       HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
   3015 }
   3016 
   3017 
   3018 HInstruction* HGraphBuilder::BuildGetNativeContext(HValue* closure) {
   3019   // Get the global object, then the native context
   3020   HInstruction* context = Add<HLoadNamedField>(
   3021       closure, nullptr, HObjectAccess::ForFunctionContextPointer());
   3022   return Add<HLoadNamedField>(
   3023       context, nullptr,
   3024       HObjectAccess::ForContextSlot(Context::NATIVE_CONTEXT_INDEX));
   3025 }
   3026 
   3027 
   3028 HValue* HGraphBuilder::BuildGetParentContext(HValue* depth, int depth_value) {
   3029   HValue* script_context = context();
   3030   if (depth != NULL) {
   3031     HValue* zero = graph()->GetConstant0();
   3032 
   3033     Push(script_context);
   3034     Push(depth);
   3035 
   3036     LoopBuilder loop(this);
   3037     loop.BeginBody(2);  // Drop script_context and depth from last environment
   3038                         // to appease live range building without simulates.
   3039     depth = Pop();
   3040     script_context = Pop();
   3041 
   3042     script_context = Add<HLoadNamedField>(
   3043         script_context, nullptr,
   3044         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   3045     depth = AddUncasted<HSub>(depth, graph()->GetConstant1());
   3046     depth->ClearFlag(HValue::kCanOverflow);
   3047 
   3048     IfBuilder if_break(this);
   3049     if_break.If<HCompareNumericAndBranch, HValue*>(depth, zero, Token::EQ);
   3050     if_break.Then();
   3051     {
   3052       Push(script_context);  // The result.
   3053       loop.Break();
   3054     }
   3055     if_break.Else();
   3056     {
   3057       Push(script_context);
   3058       Push(depth);
   3059     }
   3060     loop.EndBody();
   3061     if_break.End();
   3062 
   3063     script_context = Pop();
   3064   } else if (depth_value > 0) {
   3065     // Unroll the above loop.
   3066     for (int i = 0; i < depth_value; i++) {
   3067       script_context = Add<HLoadNamedField>(
   3068           script_context, nullptr,
   3069           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   3070     }
   3071   }
   3072   return script_context;
   3073 }
   3074 
   3075 
   3076 HInstruction* HGraphBuilder::BuildGetArrayFunction() {
   3077   HInstruction* native_context = BuildGetNativeContext();
   3078   HInstruction* index =
   3079       Add<HConstant>(static_cast<int32_t>(Context::ARRAY_FUNCTION_INDEX));
   3080   return Add<HLoadKeyed>(native_context, index, nullptr, nullptr,
   3081                          FAST_ELEMENTS);
   3082 }
   3083 
   3084 
   3085 HValue* HGraphBuilder::BuildArrayBufferViewFieldAccessor(HValue* object,
   3086                                                          HValue* checked_object,
   3087                                                          FieldIndex index) {
   3088   NoObservableSideEffectsScope scope(this);
   3089   HObjectAccess access = HObjectAccess::ForObservableJSObjectOffset(
   3090       index.offset(), Representation::Tagged());
   3091   HInstruction* buffer = Add<HLoadNamedField>(
   3092       object, checked_object, HObjectAccess::ForJSArrayBufferViewBuffer());
   3093   HInstruction* field = Add<HLoadNamedField>(object, checked_object, access);
   3094 
   3095   HInstruction* flags = Add<HLoadNamedField>(
   3096       buffer, nullptr, HObjectAccess::ForJSArrayBufferBitField());
   3097   HValue* was_neutered_mask =
   3098       Add<HConstant>(1 << JSArrayBuffer::WasNeutered::kShift);
   3099   HValue* was_neutered_test =
   3100       AddUncasted<HBitwise>(Token::BIT_AND, flags, was_neutered_mask);
   3101 
   3102   IfBuilder if_was_neutered(this);
   3103   if_was_neutered.If<HCompareNumericAndBranch>(
   3104       was_neutered_test, graph()->GetConstant0(), Token::NE);
   3105   if_was_neutered.Then();
   3106   Push(graph()->GetConstant0());
   3107   if_was_neutered.Else();
   3108   Push(field);
   3109   if_was_neutered.End();
   3110 
   3111   return Pop();
   3112 }
   3113 
   3114 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) {
   3115   HValue* native_context = BuildGetNativeContext();
   3116   HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index);
   3117   return Add<HLoadNamedField>(native_context, nullptr, function_access);
   3118 }
   3119 
   3120 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info,
   3121                                                bool track_positions)
   3122     : HGraphBuilder(info, CallInterfaceDescriptor(), track_positions),
   3123       function_state_(NULL),
   3124       initial_function_state_(this, info, NORMAL_RETURN, -1,
   3125                               TailCallMode::kAllow),
   3126       ast_context_(NULL),
   3127       break_scope_(NULL),
   3128       inlined_count_(0),
   3129       globals_(10, info->zone()),
   3130       osr_(new (info->zone()) HOsrBuilder(this)),
   3131       bounds_(info->zone()) {
   3132   // This is not initialized in the initializer list because the
   3133   // constructor for the initial state relies on function_state_ == NULL
   3134   // to know it's the initial state.
   3135   function_state_ = &initial_function_state_;
   3136   InitializeAstVisitor(info->isolate());
   3137 }
   3138 
   3139 
   3140 HBasicBlock* HOptimizedGraphBuilder::CreateJoin(HBasicBlock* first,
   3141                                                 HBasicBlock* second,
   3142                                                 BailoutId join_id) {
   3143   if (first == NULL) {
   3144     return second;
   3145   } else if (second == NULL) {
   3146     return first;
   3147   } else {
   3148     HBasicBlock* join_block = graph()->CreateBasicBlock();
   3149     Goto(first, join_block);
   3150     Goto(second, join_block);
   3151     join_block->SetJoinId(join_id);
   3152     return join_block;
   3153   }
   3154 }
   3155 
   3156 HBasicBlock* HOptimizedGraphBuilder::JoinContinue(IterationStatement* statement,
   3157                                                   BailoutId continue_id,
   3158                                                   HBasicBlock* exit_block,
   3159                                                   HBasicBlock* continue_block) {
   3160   if (continue_block != NULL) {
   3161     if (exit_block != NULL) Goto(exit_block, continue_block);
   3162     continue_block->SetJoinId(continue_id);
   3163     return continue_block;
   3164   }
   3165   return exit_block;
   3166 }
   3167 
   3168 
   3169 HBasicBlock* HOptimizedGraphBuilder::CreateLoop(IterationStatement* statement,
   3170                                                 HBasicBlock* loop_entry,
   3171                                                 HBasicBlock* body_exit,
   3172                                                 HBasicBlock* loop_successor,
   3173                                                 HBasicBlock* break_block) {
   3174   if (body_exit != NULL) Goto(body_exit, loop_entry);
   3175   loop_entry->PostProcessLoopHeader(statement);
   3176   if (break_block != NULL) {
   3177     if (loop_successor != NULL) Goto(loop_successor, break_block);
   3178     break_block->SetJoinId(statement->ExitId());
   3179     return break_block;
   3180   }
   3181   return loop_successor;
   3182 }
   3183 
   3184 
   3185 // Build a new loop header block and set it as the current block.
   3186 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry() {
   3187   HBasicBlock* loop_entry = CreateLoopHeaderBlock();
   3188   Goto(loop_entry);
   3189   set_current_block(loop_entry);
   3190   return loop_entry;
   3191 }
   3192 
   3193 
   3194 HBasicBlock* HOptimizedGraphBuilder::BuildLoopEntry(
   3195     IterationStatement* statement) {
   3196   HBasicBlock* loop_entry;
   3197 
   3198   if (osr()->HasOsrEntryAt(statement)) {
   3199     loop_entry = osr()->BuildOsrLoopEntry(statement);
   3200     if (function_state()->IsInsideDoExpressionScope()) {
   3201       Bailout(kDoExpressionUnmodelable);
   3202     }
   3203   } else {
   3204     loop_entry = BuildLoopEntry();
   3205   }
   3206   return loop_entry;
   3207 }
   3208 
   3209 
   3210 void HBasicBlock::FinishExit(HControlInstruction* instruction,
   3211                              SourcePosition position) {
   3212   Finish(instruction, position);
   3213   ClearEnvironment();
   3214 }
   3215 
   3216 
   3217 std::ostream& operator<<(std::ostream& os, const HBasicBlock& b) {
   3218   return os << "B" << b.block_id();
   3219 }
   3220 
   3221 HGraph::HGraph(CompilationInfo* info, CallInterfaceDescriptor descriptor)
   3222     : isolate_(info->isolate()),
   3223       next_block_id_(0),
   3224       entry_block_(NULL),
   3225       blocks_(8, info->zone()),
   3226       values_(16, info->zone()),
   3227       phi_list_(NULL),
   3228       uint32_instructions_(NULL),
   3229       osr_(NULL),
   3230       info_(info),
   3231       descriptor_(descriptor),
   3232       zone_(info->zone()),
   3233       allow_code_motion_(false),
   3234       use_optimistic_licm_(false),
   3235       depends_on_empty_array_proto_elements_(false),
   3236       depends_on_string_length_overflow_(false),
   3237       type_change_checksum_(0),
   3238       maximum_environment_size_(0),
   3239       no_side_effects_scope_count_(0),
   3240       disallow_adding_new_values_(false) {
   3241   if (info->IsStub()) {
   3242     // For stubs, explicitly add the context to the environment.
   3243     start_environment_ =
   3244         new (zone_) HEnvironment(zone_, descriptor.GetParameterCount() + 1);
   3245   } else {
   3246     start_environment_ =
   3247         new(zone_) HEnvironment(NULL, info->scope(), info->closure(), zone_);
   3248   }
   3249   start_environment_->set_ast_id(BailoutId::FunctionContext());
   3250   entry_block_ = CreateBasicBlock();
   3251   entry_block_->SetInitialEnvironment(start_environment_);
   3252 }
   3253 
   3254 
   3255 HBasicBlock* HGraph::CreateBasicBlock() {
   3256   HBasicBlock* result = new(zone()) HBasicBlock(this);
   3257   blocks_.Add(result, zone());
   3258   return result;
   3259 }
   3260 
   3261 
   3262 void HGraph::FinalizeUniqueness() {
   3263   DisallowHeapAllocation no_gc;
   3264   for (int i = 0; i < blocks()->length(); ++i) {
   3265     for (HInstructionIterator it(blocks()->at(i)); !it.Done(); it.Advance()) {
   3266       it.Current()->FinalizeUniqueness();
   3267     }
   3268   }
   3269 }
   3270 
   3271 
   3272 // Block ordering was implemented with two mutually recursive methods,
   3273 // HGraph::Postorder and HGraph::PostorderLoopBlocks.
   3274 // The recursion could lead to stack overflow so the algorithm has been
   3275 // implemented iteratively.
   3276 // At a high level the algorithm looks like this:
   3277 //
   3278 // Postorder(block, loop_header) : {
   3279 //   if (block has already been visited or is of another loop) return;
   3280 //   mark block as visited;
   3281 //   if (block is a loop header) {
   3282 //     VisitLoopMembers(block, loop_header);
   3283 //     VisitSuccessorsOfLoopHeader(block);
   3284 //   } else {
   3285 //     VisitSuccessors(block)
   3286 //   }
   3287 //   put block in result list;
   3288 // }
   3289 //
   3290 // VisitLoopMembers(block, outer_loop_header) {
   3291 //   foreach (block b in block loop members) {
   3292 //     VisitSuccessorsOfLoopMember(b, outer_loop_header);
   3293 //     if (b is loop header) VisitLoopMembers(b);
   3294 //   }
   3295 // }
   3296 //
   3297 // VisitSuccessorsOfLoopMember(block, outer_loop_header) {
   3298 //   foreach (block b in block successors) Postorder(b, outer_loop_header)
   3299 // }
   3300 //
   3301 // VisitSuccessorsOfLoopHeader(block) {
   3302 //   foreach (block b in block successors) Postorder(b, block)
   3303 // }
   3304 //
   3305 // VisitSuccessors(block, loop_header) {
   3306 //   foreach (block b in block successors) Postorder(b, loop_header)
   3307 // }
   3308 //
   3309 // The ordering is started calling Postorder(entry, NULL).
   3310 //
   3311 // Each instance of PostorderProcessor represents the "stack frame" of the
   3312 // recursion, and particularly keeps the state of the loop (iteration) of the
   3313 // "Visit..." function it represents.
   3314 // To recycle memory we keep all the frames in a double linked list but
   3315 // this means that we cannot use constructors to initialize the frames.
   3316 //
   3317 class PostorderProcessor : public ZoneObject {
   3318  public:
   3319   // Back link (towards the stack bottom).
   3320   PostorderProcessor* parent() {return father_; }
   3321   // Forward link (towards the stack top).
   3322   PostorderProcessor* child() {return child_; }
   3323   HBasicBlock* block() { return block_; }
   3324   HLoopInformation* loop() { return loop_; }
   3325   HBasicBlock* loop_header() { return loop_header_; }
   3326 
   3327   static PostorderProcessor* CreateEntryProcessor(Zone* zone,
   3328                                                   HBasicBlock* block) {
   3329     PostorderProcessor* result = new(zone) PostorderProcessor(NULL);
   3330     return result->SetupSuccessors(zone, block, NULL);
   3331   }
   3332 
   3333   PostorderProcessor* PerformStep(Zone* zone,
   3334                                   ZoneList<HBasicBlock*>* order) {
   3335     PostorderProcessor* next =
   3336         PerformNonBacktrackingStep(zone, order);
   3337     if (next != NULL) {
   3338       return next;
   3339     } else {
   3340       return Backtrack(zone, order);
   3341     }
   3342   }
   3343 
   3344  private:
   3345   explicit PostorderProcessor(PostorderProcessor* father)
   3346       : father_(father), child_(NULL), successor_iterator(NULL) { }
   3347 
   3348   // Each enum value states the cycle whose state is kept by this instance.
   3349   enum LoopKind {
   3350     NONE,
   3351     SUCCESSORS,
   3352     SUCCESSORS_OF_LOOP_HEADER,
   3353     LOOP_MEMBERS,
   3354     SUCCESSORS_OF_LOOP_MEMBER
   3355   };
   3356 
   3357   // Each "Setup..." method is like a constructor for a cycle state.
   3358   PostorderProcessor* SetupSuccessors(Zone* zone,
   3359                                       HBasicBlock* block,
   3360                                       HBasicBlock* loop_header) {
   3361     if (block == NULL || block->IsOrdered() ||
   3362         block->parent_loop_header() != loop_header) {
   3363       kind_ = NONE;
   3364       block_ = NULL;
   3365       loop_ = NULL;
   3366       loop_header_ = NULL;
   3367       return this;
   3368     } else {
   3369       block_ = block;
   3370       loop_ = NULL;
   3371       block->MarkAsOrdered();
   3372 
   3373       if (block->IsLoopHeader()) {
   3374         kind_ = SUCCESSORS_OF_LOOP_HEADER;
   3375         loop_header_ = block;
   3376         InitializeSuccessors();
   3377         PostorderProcessor* result = Push(zone);
   3378         return result->SetupLoopMembers(zone, block, block->loop_information(),
   3379                                         loop_header);
   3380       } else {
   3381         DCHECK(block->IsFinished());
   3382         kind_ = SUCCESSORS;
   3383         loop_header_ = loop_header;
   3384         InitializeSuccessors();
   3385         return this;
   3386       }
   3387     }
   3388   }
   3389 
   3390   PostorderProcessor* SetupLoopMembers(Zone* zone,
   3391                                        HBasicBlock* block,
   3392                                        HLoopInformation* loop,
   3393                                        HBasicBlock* loop_header) {
   3394     kind_ = LOOP_MEMBERS;
   3395     block_ = block;
   3396     loop_ = loop;
   3397     loop_header_ = loop_header;
   3398     InitializeLoopMembers();
   3399     return this;
   3400   }
   3401 
   3402   PostorderProcessor* SetupSuccessorsOfLoopMember(
   3403       HBasicBlock* block,
   3404       HLoopInformation* loop,
   3405       HBasicBlock* loop_header) {
   3406     kind_ = SUCCESSORS_OF_LOOP_MEMBER;
   3407     block_ = block;
   3408     loop_ = loop;
   3409     loop_header_ = loop_header;
   3410     InitializeSuccessors();
   3411     return this;
   3412   }
   3413 
   3414   // This method "allocates" a new stack frame.
   3415   PostorderProcessor* Push(Zone* zone) {
   3416     if (child_ == NULL) {
   3417       child_ = new(zone) PostorderProcessor(this);
   3418     }
   3419     return child_;
   3420   }
   3421 
   3422   void ClosePostorder(ZoneList<HBasicBlock*>* order, Zone* zone) {
   3423     DCHECK(block_->end()->FirstSuccessor() == NULL ||
   3424            order->Contains(block_->end()->FirstSuccessor()) ||
   3425            block_->end()->FirstSuccessor()->IsLoopHeader());
   3426     DCHECK(block_->end()->SecondSuccessor() == NULL ||
   3427            order->Contains(block_->end()->SecondSuccessor()) ||
   3428            block_->end()->SecondSuccessor()->IsLoopHeader());
   3429     order->Add(block_, zone);
   3430   }
   3431 
   3432   // This method is the basic block to walk up the stack.
   3433   PostorderProcessor* Pop(Zone* zone,
   3434                           ZoneList<HBasicBlock*>* order) {
   3435     switch (kind_) {
   3436       case SUCCESSORS:
   3437       case SUCCESSORS_OF_LOOP_HEADER:
   3438         ClosePostorder(order, zone);
   3439         return father_;
   3440       case LOOP_MEMBERS:
   3441         return father_;
   3442       case SUCCESSORS_OF_LOOP_MEMBER:
   3443         if (block()->IsLoopHeader() && block() != loop_->loop_header()) {
   3444           // In this case we need to perform a LOOP_MEMBERS cycle so we
   3445           // initialize it and return this instead of father.
   3446           return SetupLoopMembers(zone, block(),
   3447                                   block()->loop_information(), loop_header_);
   3448         } else {
   3449           return father_;
   3450         }
   3451       case NONE:
   3452         return father_;
   3453     }
   3454     UNREACHABLE();
   3455     return NULL;
   3456   }
   3457 
   3458   // Walks up the stack.
   3459   PostorderProcessor* Backtrack(Zone* zone,
   3460                                 ZoneList<HBasicBlock*>* order) {
   3461     PostorderProcessor* parent = Pop(zone, order);
   3462     while (parent != NULL) {
   3463       PostorderProcessor* next =
   3464           parent->PerformNonBacktrackingStep(zone, order);
   3465       if (next != NULL) {
   3466         return next;
   3467       } else {
   3468         parent = parent->Pop(zone, order);
   3469       }
   3470     }
   3471     return NULL;
   3472   }
   3473 
   3474   PostorderProcessor* PerformNonBacktrackingStep(
   3475       Zone* zone,
   3476       ZoneList<HBasicBlock*>* order) {
   3477     HBasicBlock* next_block;
   3478     switch (kind_) {
   3479       case SUCCESSORS:
   3480         next_block = AdvanceSuccessors();
   3481         if (next_block != NULL) {
   3482           PostorderProcessor* result = Push(zone);
   3483           return result->SetupSuccessors(zone, next_block, loop_header_);
   3484         }
   3485         break;
   3486       case SUCCESSORS_OF_LOOP_HEADER:
   3487         next_block = AdvanceSuccessors();
   3488         if (next_block != NULL) {
   3489           PostorderProcessor* result = Push(zone);
   3490           return result->SetupSuccessors(zone, next_block, block());
   3491         }
   3492         break;
   3493       case LOOP_MEMBERS:
   3494         next_block = AdvanceLoopMembers();
   3495         if (next_block != NULL) {
   3496           PostorderProcessor* result = Push(zone);
   3497           return result->SetupSuccessorsOfLoopMember(next_block,
   3498                                                      loop_, loop_header_);
   3499         }
   3500         break;
   3501       case SUCCESSORS_OF_LOOP_MEMBER:
   3502         next_block = AdvanceSuccessors();
   3503         if (next_block != NULL) {
   3504           PostorderProcessor* result = Push(zone);
   3505           return result->SetupSuccessors(zone, next_block, loop_header_);
   3506         }
   3507         break;
   3508       case NONE:
   3509         return NULL;
   3510     }
   3511     return NULL;
   3512   }
   3513 
   3514   // The following two methods implement a "foreach b in successors" cycle.
   3515   void InitializeSuccessors() {
   3516     loop_index = 0;
   3517     loop_length = 0;
   3518     successor_iterator = HSuccessorIterator(block_->end());
   3519   }
   3520 
   3521   HBasicBlock* AdvanceSuccessors() {
   3522     if (!successor_iterator.Done()) {
   3523       HBasicBlock* result = successor_iterator.Current();
   3524       successor_iterator.Advance();
   3525       return result;
   3526     }
   3527     return NULL;
   3528   }
   3529 
   3530   // The following two methods implement a "foreach b in loop members" cycle.
   3531   void InitializeLoopMembers() {
   3532     loop_index = 0;
   3533     loop_length = loop_->blocks()->length();
   3534   }
   3535 
   3536   HBasicBlock* AdvanceLoopMembers() {
   3537     if (loop_index < loop_length) {
   3538       HBasicBlock* result = loop_->blocks()->at(loop_index);
   3539       loop_index++;
   3540       return result;
   3541     } else {
   3542       return NULL;
   3543     }
   3544   }
   3545 
   3546   LoopKind kind_;
   3547   PostorderProcessor* father_;
   3548   PostorderProcessor* child_;
   3549   HLoopInformation* loop_;
   3550   HBasicBlock* block_;
   3551   HBasicBlock* loop_header_;
   3552   int loop_index;
   3553   int loop_length;
   3554   HSuccessorIterator successor_iterator;
   3555 };
   3556 
   3557 
   3558 void HGraph::OrderBlocks() {
   3559   CompilationPhase phase("H_Block ordering", info());
   3560 
   3561 #ifdef DEBUG
   3562   // Initially the blocks must not be ordered.
   3563   for (int i = 0; i < blocks_.length(); ++i) {
   3564     DCHECK(!blocks_[i]->IsOrdered());
   3565   }
   3566 #endif
   3567 
   3568   PostorderProcessor* postorder =
   3569       PostorderProcessor::CreateEntryProcessor(zone(), blocks_[0]);
   3570   blocks_.Rewind(0);
   3571   while (postorder) {
   3572     postorder = postorder->PerformStep(zone(), &blocks_);
   3573   }
   3574 
   3575 #ifdef DEBUG
   3576   // Now all blocks must be marked as ordered.
   3577   for (int i = 0; i < blocks_.length(); ++i) {
   3578     DCHECK(blocks_[i]->IsOrdered());
   3579   }
   3580 #endif
   3581 
   3582   // Reverse block list and assign block IDs.
   3583   for (int i = 0, j = blocks_.length(); --j >= i; ++i) {
   3584     HBasicBlock* bi = blocks_[i];
   3585     HBasicBlock* bj = blocks_[j];
   3586     bi->set_block_id(j);
   3587     bj->set_block_id(i);
   3588     blocks_[i] = bj;
   3589     blocks_[j] = bi;
   3590   }
   3591 }
   3592 
   3593 
   3594 void HGraph::AssignDominators() {
   3595   HPhase phase("H_Assign dominators", this);
   3596   for (int i = 0; i < blocks_.length(); ++i) {
   3597     HBasicBlock* block = blocks_[i];
   3598     if (block->IsLoopHeader()) {
   3599       // Only the first predecessor of a loop header is from outside the loop.
   3600       // All others are back edges, and thus cannot dominate the loop header.
   3601       block->AssignCommonDominator(block->predecessors()->first());
   3602       block->AssignLoopSuccessorDominators();
   3603     } else {
   3604       for (int j = blocks_[i]->predecessors()->length() - 1; j >= 0; --j) {
   3605         blocks_[i]->AssignCommonDominator(blocks_[i]->predecessors()->at(j));
   3606       }
   3607     }
   3608   }
   3609 }
   3610 
   3611 
   3612 bool HGraph::CheckArgumentsPhiUses() {
   3613   int block_count = blocks_.length();
   3614   for (int i = 0; i < block_count; ++i) {
   3615     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   3616       HPhi* phi = blocks_[i]->phis()->at(j);
   3617       // We don't support phi uses of arguments for now.
   3618       if (phi->CheckFlag(HValue::kIsArguments)) return false;
   3619     }
   3620   }
   3621   return true;
   3622 }
   3623 
   3624 
   3625 bool HGraph::CheckConstPhiUses() {
   3626   int block_count = blocks_.length();
   3627   for (int i = 0; i < block_count; ++i) {
   3628     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   3629       HPhi* phi = blocks_[i]->phis()->at(j);
   3630       // Check for the hole value (from an uninitialized const).
   3631       for (int k = 0; k < phi->OperandCount(); k++) {
   3632         if (phi->OperandAt(k) == GetConstantHole()) return false;
   3633       }
   3634     }
   3635   }
   3636   return true;
   3637 }
   3638 
   3639 
   3640 void HGraph::CollectPhis() {
   3641   int block_count = blocks_.length();
   3642   phi_list_ = new(zone()) ZoneList<HPhi*>(block_count, zone());
   3643   for (int i = 0; i < block_count; ++i) {
   3644     for (int j = 0; j < blocks_[i]->phis()->length(); ++j) {
   3645       HPhi* phi = blocks_[i]->phis()->at(j);
   3646       phi_list_->Add(phi, zone());
   3647     }
   3648   }
   3649 }
   3650 
   3651 
   3652 // Implementation of utility class to encapsulate the translation state for
   3653 // a (possibly inlined) function.
   3654 FunctionState::FunctionState(HOptimizedGraphBuilder* owner,
   3655                              CompilationInfo* info, InliningKind inlining_kind,
   3656                              int inlining_id, TailCallMode tail_call_mode)
   3657     : owner_(owner),
   3658       compilation_info_(info),
   3659       call_context_(NULL),
   3660       inlining_kind_(inlining_kind),
   3661       tail_call_mode_(tail_call_mode),
   3662       function_return_(NULL),
   3663       test_context_(NULL),
   3664       entry_(NULL),
   3665       arguments_object_(NULL),
   3666       arguments_elements_(NULL),
   3667       inlining_id_(inlining_id),
   3668       outer_source_position_(SourcePosition::Unknown()),
   3669       do_expression_scope_count_(0),
   3670       outer_(owner->function_state()) {
   3671   if (outer_ != NULL) {
   3672     // State for an inline function.
   3673     if (owner->ast_context()->IsTest()) {
   3674       HBasicBlock* if_true = owner->graph()->CreateBasicBlock();
   3675       HBasicBlock* if_false = owner->graph()->CreateBasicBlock();
   3676       if_true->MarkAsInlineReturnTarget(owner->current_block());
   3677       if_false->MarkAsInlineReturnTarget(owner->current_block());
   3678       TestContext* outer_test_context = TestContext::cast(owner->ast_context());
   3679       Expression* cond = outer_test_context->condition();
   3680       // The AstContext constructor pushed on the context stack.  This newed
   3681       // instance is the reason that AstContext can't be BASE_EMBEDDED.
   3682       test_context_ = new TestContext(owner, cond, if_true, if_false);
   3683     } else {
   3684       function_return_ = owner->graph()->CreateBasicBlock();
   3685       function_return()->MarkAsInlineReturnTarget(owner->current_block());
   3686     }
   3687     // Set this after possibly allocating a new TestContext above.
   3688     call_context_ = owner->ast_context();
   3689   }
   3690 
   3691   // Push on the state stack.
   3692   owner->set_function_state(this);
   3693 
   3694   if (owner->is_tracking_positions()) {
   3695     outer_source_position_ = owner->source_position();
   3696     owner->EnterInlinedSource(inlining_id);
   3697     owner->SetSourcePosition(info->shared_info()->start_position());
   3698   }
   3699 }
   3700 
   3701 
   3702 FunctionState::~FunctionState() {
   3703   delete test_context_;
   3704   owner_->set_function_state(outer_);
   3705 
   3706   if (owner_->is_tracking_positions()) {
   3707     owner_->set_source_position(outer_source_position_);
   3708     owner_->EnterInlinedSource(outer_->inlining_id());
   3709   }
   3710 }
   3711 
   3712 
   3713 // Implementation of utility classes to represent an expression's context in
   3714 // the AST.
   3715 AstContext::AstContext(HOptimizedGraphBuilder* owner, Expression::Context kind)
   3716     : owner_(owner),
   3717       kind_(kind),
   3718       outer_(owner->ast_context()),
   3719       typeof_mode_(NOT_INSIDE_TYPEOF) {
   3720   owner->set_ast_context(this);  // Push.
   3721 #ifdef DEBUG
   3722   DCHECK_EQ(JS_FUNCTION, owner->environment()->frame_type());
   3723   original_length_ = owner->environment()->length();
   3724 #endif
   3725 }
   3726 
   3727 
   3728 AstContext::~AstContext() {
   3729   owner_->set_ast_context(outer_);  // Pop.
   3730 }
   3731 
   3732 
   3733 EffectContext::~EffectContext() {
   3734   DCHECK(owner()->HasStackOverflow() || owner()->current_block() == NULL ||
   3735          (owner()->environment()->length() == original_length_ &&
   3736           (owner()->environment()->frame_type() == JS_FUNCTION ||
   3737            owner()->environment()->frame_type() == TAIL_CALLER_FUNCTION)));
   3738 }
   3739 
   3740 
   3741 ValueContext::~ValueContext() {
   3742   DCHECK(owner()->HasStackOverflow() || owner()->current_block() == NULL ||
   3743          (owner()->environment()->length() == original_length_ + 1 &&
   3744           (owner()->environment()->frame_type() == JS_FUNCTION ||
   3745            owner()->environment()->frame_type() == TAIL_CALLER_FUNCTION)));
   3746 }
   3747 
   3748 
   3749 void EffectContext::ReturnValue(HValue* value) {
   3750   // The value is simply ignored.
   3751 }
   3752 
   3753 
   3754 void ValueContext::ReturnValue(HValue* value) {
   3755   // The value is tracked in the bailout environment, and communicated
   3756   // through the environment as the result of the expression.
   3757   if (value->CheckFlag(HValue::kIsArguments)) {
   3758     if (flag_ == ARGUMENTS_FAKED) {
   3759       value = owner()->graph()->GetConstantUndefined();
   3760     } else if (!arguments_allowed()) {
   3761       owner()->Bailout(kBadValueContextForArgumentsValue);
   3762     }
   3763   }
   3764   owner()->Push(value);
   3765 }
   3766 
   3767 
   3768 void TestContext::ReturnValue(HValue* value) {
   3769   BuildBranch(value);
   3770 }
   3771 
   3772 
   3773 void EffectContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   3774   DCHECK(!instr->IsControlInstruction());
   3775   owner()->AddInstruction(instr);
   3776   if (instr->HasObservableSideEffects()) {
   3777     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   3778   }
   3779 }
   3780 
   3781 
   3782 void EffectContext::ReturnControl(HControlInstruction* instr,
   3783                                   BailoutId ast_id) {
   3784   DCHECK(!instr->HasObservableSideEffects());
   3785   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
   3786   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
   3787   instr->SetSuccessorAt(0, empty_true);
   3788   instr->SetSuccessorAt(1, empty_false);
   3789   owner()->FinishCurrentBlock(instr);
   3790   HBasicBlock* join = owner()->CreateJoin(empty_true, empty_false, ast_id);
   3791   owner()->set_current_block(join);
   3792 }
   3793 
   3794 
   3795 void EffectContext::ReturnContinuation(HIfContinuation* continuation,
   3796                                        BailoutId ast_id) {
   3797   HBasicBlock* true_branch = NULL;
   3798   HBasicBlock* false_branch = NULL;
   3799   continuation->Continue(&true_branch, &false_branch);
   3800   if (!continuation->IsTrueReachable()) {
   3801     owner()->set_current_block(false_branch);
   3802   } else if (!continuation->IsFalseReachable()) {
   3803     owner()->set_current_block(true_branch);
   3804   } else {
   3805     HBasicBlock* join = owner()->CreateJoin(true_branch, false_branch, ast_id);
   3806     owner()->set_current_block(join);
   3807   }
   3808 }
   3809 
   3810 
   3811 void ValueContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   3812   DCHECK(!instr->IsControlInstruction());
   3813   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
   3814     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
   3815   }
   3816   owner()->AddInstruction(instr);
   3817   owner()->Push(instr);
   3818   if (instr->HasObservableSideEffects()) {
   3819     owner()->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   3820   }
   3821 }
   3822 
   3823 
   3824 void ValueContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
   3825   DCHECK(!instr->HasObservableSideEffects());
   3826   if (!arguments_allowed() && instr->CheckFlag(HValue::kIsArguments)) {
   3827     return owner()->Bailout(kBadValueContextForArgumentsObjectValue);
   3828   }
   3829   HBasicBlock* materialize_false = owner()->graph()->CreateBasicBlock();
   3830   HBasicBlock* materialize_true = owner()->graph()->CreateBasicBlock();
   3831   instr->SetSuccessorAt(0, materialize_true);
   3832   instr->SetSuccessorAt(1, materialize_false);
   3833   owner()->FinishCurrentBlock(instr);
   3834   owner()->set_current_block(materialize_true);
   3835   owner()->Push(owner()->graph()->GetConstantTrue());
   3836   owner()->set_current_block(materialize_false);
   3837   owner()->Push(owner()->graph()->GetConstantFalse());
   3838   HBasicBlock* join =
   3839     owner()->CreateJoin(materialize_true, materialize_false, ast_id);
   3840   owner()->set_current_block(join);
   3841 }
   3842 
   3843 
   3844 void ValueContext::ReturnContinuation(HIfContinuation* continuation,
   3845                                       BailoutId ast_id) {
   3846   HBasicBlock* materialize_true = NULL;
   3847   HBasicBlock* materialize_false = NULL;
   3848   continuation->Continue(&materialize_true, &materialize_false);
   3849   if (continuation->IsTrueReachable()) {
   3850     owner()->set_current_block(materialize_true);
   3851     owner()->Push(owner()->graph()->GetConstantTrue());
   3852     owner()->set_current_block(materialize_true);
   3853   }
   3854   if (continuation->IsFalseReachable()) {
   3855     owner()->set_current_block(materialize_false);
   3856     owner()->Push(owner()->graph()->GetConstantFalse());
   3857     owner()->set_current_block(materialize_false);
   3858   }
   3859   if (continuation->TrueAndFalseReachable()) {
   3860     HBasicBlock* join =
   3861         owner()->CreateJoin(materialize_true, materialize_false, ast_id);
   3862     owner()->set_current_block(join);
   3863   }
   3864 }
   3865 
   3866 
   3867 void TestContext::ReturnInstruction(HInstruction* instr, BailoutId ast_id) {
   3868   DCHECK(!instr->IsControlInstruction());
   3869   HOptimizedGraphBuilder* builder = owner();
   3870   builder->AddInstruction(instr);
   3871   // We expect a simulate after every expression with side effects, though
   3872   // this one isn't actually needed (and wouldn't work if it were targeted).
   3873   if (instr->HasObservableSideEffects()) {
   3874     builder->Push(instr);
   3875     builder->Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   3876     builder->Pop();
   3877   }
   3878   BuildBranch(instr);
   3879 }
   3880 
   3881 
   3882 void TestContext::ReturnControl(HControlInstruction* instr, BailoutId ast_id) {
   3883   DCHECK(!instr->HasObservableSideEffects());
   3884   HBasicBlock* empty_true = owner()->graph()->CreateBasicBlock();
   3885   HBasicBlock* empty_false = owner()->graph()->CreateBasicBlock();
   3886   instr->SetSuccessorAt(0, empty_true);
   3887   instr->SetSuccessorAt(1, empty_false);
   3888   owner()->FinishCurrentBlock(instr);
   3889   owner()->Goto(empty_true, if_true(), owner()->function_state());
   3890   owner()->Goto(empty_false, if_false(), owner()->function_state());
   3891   owner()->set_current_block(NULL);
   3892 }
   3893 
   3894 
   3895 void TestContext::ReturnContinuation(HIfContinuation* continuation,
   3896                                      BailoutId ast_id) {
   3897   HBasicBlock* true_branch = NULL;
   3898   HBasicBlock* false_branch = NULL;
   3899   continuation->Continue(&true_branch, &false_branch);
   3900   if (continuation->IsTrueReachable()) {
   3901     owner()->Goto(true_branch, if_true(), owner()->function_state());
   3902   }
   3903   if (continuation->IsFalseReachable()) {
   3904     owner()->Goto(false_branch, if_false(), owner()->function_state());
   3905   }
   3906   owner()->set_current_block(NULL);
   3907 }
   3908 
   3909 
   3910 void TestContext::BuildBranch(HValue* value) {
   3911   // We expect the graph to be in edge-split form: there is no edge that
   3912   // connects a branch node to a join node.  We conservatively ensure that
   3913   // property by always adding an empty block on the outgoing edges of this
   3914   // branch.
   3915   HOptimizedGraphBuilder* builder = owner();
   3916   if (value != NULL && value->CheckFlag(HValue::kIsArguments)) {
   3917     builder->Bailout(kArgumentsObjectValueInATestContext);
   3918   }
   3919   ToBooleanHints expected(condition()->to_boolean_types());
   3920   ReturnControl(owner()->New<HBranch>(value, expected), BailoutId::None());
   3921 }
   3922 
   3923 
   3924 // HOptimizedGraphBuilder infrastructure for bailing out and checking bailouts.
   3925 #define CHECK_BAILOUT(call)                     \
   3926   do {                                          \
   3927     call;                                       \
   3928     if (HasStackOverflow()) return;             \
   3929   } while (false)
   3930 
   3931 
   3932 #define CHECK_ALIVE(call)                                       \
   3933   do {                                                          \
   3934     call;                                                       \
   3935     if (HasStackOverflow() || current_block() == NULL) return;  \
   3936   } while (false)
   3937 
   3938 
   3939 #define CHECK_ALIVE_OR_RETURN(call, value)                            \
   3940   do {                                                                \
   3941     call;                                                             \
   3942     if (HasStackOverflow() || current_block() == NULL) return value;  \
   3943   } while (false)
   3944 
   3945 
   3946 void HOptimizedGraphBuilder::Bailout(BailoutReason reason) {
   3947   current_info()->AbortOptimization(reason);
   3948   SetStackOverflow();
   3949 }
   3950 
   3951 
   3952 void HOptimizedGraphBuilder::VisitForEffect(Expression* expr) {
   3953   EffectContext for_effect(this);
   3954   Visit(expr);
   3955 }
   3956 
   3957 
   3958 void HOptimizedGraphBuilder::VisitForValue(Expression* expr,
   3959                                            ArgumentsAllowedFlag flag) {
   3960   ValueContext for_value(this, flag);
   3961   Visit(expr);
   3962 }
   3963 
   3964 
   3965 void HOptimizedGraphBuilder::VisitForTypeOf(Expression* expr) {
   3966   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
   3967   for_value.set_typeof_mode(INSIDE_TYPEOF);
   3968   Visit(expr);
   3969 }
   3970 
   3971 
   3972 void HOptimizedGraphBuilder::VisitForControl(Expression* expr,
   3973                                              HBasicBlock* true_block,
   3974                                              HBasicBlock* false_block) {
   3975   TestContext for_control(this, expr, true_block, false_block);
   3976   Visit(expr);
   3977 }
   3978 
   3979 
   3980 void HOptimizedGraphBuilder::VisitExpressions(
   3981     ZoneList<Expression*>* exprs) {
   3982   for (int i = 0; i < exprs->length(); ++i) {
   3983     CHECK_ALIVE(VisitForValue(exprs->at(i)));
   3984   }
   3985 }
   3986 
   3987 
   3988 void HOptimizedGraphBuilder::VisitExpressions(ZoneList<Expression*>* exprs,
   3989                                               ArgumentsAllowedFlag flag) {
   3990   for (int i = 0; i < exprs->length(); ++i) {
   3991     CHECK_ALIVE(VisitForValue(exprs->at(i), flag));
   3992   }
   3993 }
   3994 
   3995 
   3996 bool HOptimizedGraphBuilder::BuildGraph() {
   3997   if (IsSubclassConstructor(current_info()->literal()->kind())) {
   3998     Bailout(kSuperReference);
   3999     return false;
   4000   }
   4001 
   4002   DeclarationScope* scope = current_info()->scope();
   4003   SetUpScope(scope);
   4004 
   4005   // Add an edge to the body entry.  This is warty: the graph's start
   4006   // environment will be used by the Lithium translation as the initial
   4007   // environment on graph entry, but it has now been mutated by the
   4008   // Hydrogen translation of the instructions in the start block.  This
   4009   // environment uses values which have not been defined yet.  These
   4010   // Hydrogen instructions will then be replayed by the Lithium
   4011   // translation, so they cannot have an environment effect.  The edge to
   4012   // the body's entry block (along with some special logic for the start
   4013   // block in HInstruction::InsertAfter) seals the start block from
   4014   // getting unwanted instructions inserted.
   4015   //
   4016   // TODO(kmillikin): Fix this.  Stop mutating the initial environment.
   4017   // Make the Hydrogen instructions in the initial block into Hydrogen
   4018   // values (but not instructions), present in the initial environment and
   4019   // not replayed by the Lithium translation.
   4020   HEnvironment* initial_env = environment()->CopyWithoutHistory();
   4021   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
   4022   Goto(body_entry);
   4023   body_entry->SetJoinId(BailoutId::FunctionEntry());
   4024   set_current_block(body_entry);
   4025 
   4026   VisitDeclarations(scope->declarations());
   4027   Add<HSimulate>(BailoutId::Declarations());
   4028 
   4029   Add<HStackCheck>(HStackCheck::kFunctionEntry);
   4030 
   4031   VisitStatements(current_info()->literal()->body());
   4032   if (HasStackOverflow()) return false;
   4033 
   4034   if (current_block() != NULL) {
   4035     Add<HReturn>(graph()->GetConstantUndefined());
   4036     set_current_block(NULL);
   4037   }
   4038 
   4039   // If the checksum of the number of type info changes is the same as the
   4040   // last time this function was compiled, then this recompile is likely not
   4041   // due to missing/inadequate type feedback, but rather too aggressive
   4042   // optimization. Disable optimistic LICM in that case.
   4043   Handle<Code> unoptimized_code(current_info()->shared_info()->code());
   4044   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
   4045   Handle<TypeFeedbackInfo> type_info(
   4046       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
   4047   int checksum = type_info->own_type_change_checksum();
   4048   int composite_checksum = graph()->update_type_change_checksum(checksum);
   4049   graph()->set_use_optimistic_licm(
   4050       !type_info->matches_inlined_type_change_checksum(composite_checksum));
   4051   type_info->set_inlined_type_change_checksum(composite_checksum);
   4052 
   4053   // Set this predicate early to avoid handle deref during graph optimization.
   4054   graph()->set_allow_code_motion(
   4055       current_info()->IsStub() ||
   4056       current_info()->shared_info()->opt_count() + 1 < FLAG_max_opt_count);
   4057 
   4058   // Perform any necessary OSR-specific cleanups or changes to the graph.
   4059   osr()->FinishGraph();
   4060 
   4061   return true;
   4062 }
   4063 
   4064 
   4065 bool HGraph::Optimize(BailoutReason* bailout_reason) {
   4066   OrderBlocks();
   4067   AssignDominators();
   4068 
   4069   // We need to create a HConstant "zero" now so that GVN will fold every
   4070   // zero-valued constant in the graph together.
   4071   // The constant is needed to make idef-based bounds check work: the pass
   4072   // evaluates relations with "zero" and that zero cannot be created after GVN.
   4073   GetConstant0();
   4074 
   4075 #ifdef DEBUG
   4076   // Do a full verify after building the graph and computing dominators.
   4077   Verify(true);
   4078 #endif
   4079 
   4080   if (FLAG_analyze_environment_liveness && maximum_environment_size() != 0) {
   4081     Run<HEnvironmentLivenessAnalysisPhase>();
   4082   }
   4083 
   4084   if (!CheckConstPhiUses()) {
   4085     *bailout_reason = kUnsupportedPhiUseOfConstVariable;
   4086     return false;
   4087   }
   4088   Run<HRedundantPhiEliminationPhase>();
   4089   if (!CheckArgumentsPhiUses()) {
   4090     *bailout_reason = kUnsupportedPhiUseOfArguments;
   4091     return false;
   4092   }
   4093 
   4094   // Find and mark unreachable code to simplify optimizations, especially gvn,
   4095   // where unreachable code could unnecessarily defeat LICM.
   4096   Run<HMarkUnreachableBlocksPhase>();
   4097 
   4098   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
   4099   if (FLAG_use_escape_analysis) Run<HEscapeAnalysisPhase>();
   4100 
   4101   if (FLAG_load_elimination) Run<HLoadEliminationPhase>();
   4102 
   4103   CollectPhis();
   4104 
   4105   if (has_osr()) osr()->FinishOsrValues();
   4106 
   4107   Run<HInferRepresentationPhase>();
   4108 
   4109   // Remove HSimulate instructions that have turned out not to be needed
   4110   // after all by folding them into the following HSimulate.
   4111   // This must happen after inferring representations.
   4112   Run<HMergeRemovableSimulatesPhase>();
   4113 
   4114   Run<HRepresentationChangesPhase>();
   4115 
   4116   Run<HInferTypesPhase>();
   4117 
   4118   // Must be performed before canonicalization to ensure that Canonicalize
   4119   // will not remove semantically meaningful ToInt32 operations e.g. BIT_OR with
   4120   // zero.
   4121   Run<HUint32AnalysisPhase>();
   4122 
   4123   if (FLAG_use_canonicalizing) Run<HCanonicalizePhase>();
   4124 
   4125   if (FLAG_use_gvn) Run<HGlobalValueNumberingPhase>();
   4126 
   4127   if (FLAG_check_elimination) Run<HCheckEliminationPhase>();
   4128 
   4129   if (FLAG_store_elimination) Run<HStoreEliminationPhase>();
   4130 
   4131   Run<HRangeAnalysisPhase>();
   4132 
   4133   // Eliminate redundant stack checks on backwards branches.
   4134   Run<HStackCheckEliminationPhase>();
   4135 
   4136   if (FLAG_array_bounds_checks_elimination) Run<HBoundsCheckEliminationPhase>();
   4137   if (FLAG_array_index_dehoisting) Run<HDehoistIndexComputationsPhase>();
   4138   if (FLAG_dead_code_elimination) Run<HDeadCodeEliminationPhase>();
   4139 
   4140   RestoreActualValues();
   4141 
   4142   // Find unreachable code a second time, GVN and other optimizations may have
   4143   // made blocks unreachable that were previously reachable.
   4144   Run<HMarkUnreachableBlocksPhase>();
   4145 
   4146   return true;
   4147 }
   4148 
   4149 
   4150 void HGraph::RestoreActualValues() {
   4151   HPhase phase("H_Restore actual values", this);
   4152 
   4153   for (int block_index = 0; block_index < blocks()->length(); block_index++) {
   4154     HBasicBlock* block = blocks()->at(block_index);
   4155 
   4156 #ifdef DEBUG
   4157     for (int i = 0; i < block->phis()->length(); i++) {
   4158       HPhi* phi = block->phis()->at(i);
   4159       DCHECK(phi->ActualValue() == phi);
   4160     }
   4161 #endif
   4162 
   4163     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
   4164       HInstruction* instruction = it.Current();
   4165       if (instruction->ActualValue() == instruction) continue;
   4166       if (instruction->CheckFlag(HValue::kIsDead)) {
   4167         // The instruction was marked as deleted but left in the graph
   4168         // as a control flow dependency point for subsequent
   4169         // instructions.
   4170         instruction->DeleteAndReplaceWith(instruction->ActualValue());
   4171       } else {
   4172         DCHECK(instruction->IsInformativeDefinition());
   4173         if (instruction->IsPurelyInformativeDefinition()) {
   4174           instruction->DeleteAndReplaceWith(instruction->RedefinedOperand());
   4175         } else {
   4176           instruction->ReplaceAllUsesWith(instruction->ActualValue());
   4177         }
   4178       }
   4179     }
   4180   }
   4181 }
   4182 
   4183 
   4184 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) {
   4185   ZoneList<HValue*> arguments(count, zone());
   4186   for (int i = 0; i < count; ++i) {
   4187     arguments.Add(Pop(), zone());
   4188   }
   4189 
   4190   HPushArguments* push_args = New<HPushArguments>();
   4191   while (!arguments.is_empty()) {
   4192     push_args->AddInput(arguments.RemoveLast());
   4193   }
   4194   AddInstruction(push_args);
   4195 }
   4196 
   4197 
   4198 template <class Instruction>
   4199 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) {
   4200   PushArgumentsFromEnvironment(call->argument_count());
   4201   return call;
   4202 }
   4203 
   4204 void HOptimizedGraphBuilder::SetUpScope(DeclarationScope* scope) {
   4205   HEnvironment* prolog_env = environment();
   4206   int parameter_count = environment()->parameter_count();
   4207   ZoneList<HValue*> parameters(parameter_count, zone());
   4208   for (int i = 0; i < parameter_count; ++i) {
   4209     HInstruction* parameter = Add<HParameter>(static_cast<unsigned>(i));
   4210     parameters.Add(parameter, zone());
   4211     environment()->Bind(i, parameter);
   4212   }
   4213 
   4214   HConstant* undefined_constant = graph()->GetConstantUndefined();
   4215   // Initialize specials and locals to undefined.
   4216   for (int i = parameter_count + 1; i < environment()->length(); ++i) {
   4217     environment()->Bind(i, undefined_constant);
   4218   }
   4219   Add<HPrologue>();
   4220 
   4221   HEnvironment* initial_env = environment()->CopyWithoutHistory();
   4222   HBasicBlock* body_entry = CreateBasicBlock(initial_env);
   4223   GotoNoSimulate(body_entry);
   4224   set_current_block(body_entry);
   4225 
   4226   // Initialize context of prolog environment to undefined.
   4227   prolog_env->BindContext(undefined_constant);
   4228 
   4229   // First special is HContext.
   4230   HInstruction* context = Add<HContext>();
   4231   environment()->BindContext(context);
   4232 
   4233   // Create an arguments object containing the initial parameters.  Set the
   4234   // initial values of parameters including "this" having parameter index 0.
   4235   DCHECK_EQ(scope->num_parameters() + 1, parameter_count);
   4236   HArgumentsObject* arguments_object = New<HArgumentsObject>(parameter_count);
   4237   for (int i = 0; i < parameter_count; ++i) {
   4238     HValue* parameter = parameters.at(i);
   4239     arguments_object->AddArgument(parameter, zone());
   4240   }
   4241 
   4242   AddInstruction(arguments_object);
   4243 
   4244   // Handle the arguments and arguments shadow variables specially (they do
   4245   // not have declarations).
   4246   if (scope->arguments() != NULL) {
   4247     environment()->Bind(scope->arguments(), arguments_object);
   4248   }
   4249 
   4250   if (scope->rest_parameter() != nullptr) {
   4251     return Bailout(kRestParameter);
   4252   }
   4253 
   4254   if (scope->this_function_var() != nullptr ||
   4255       scope->new_target_var() != nullptr) {
   4256     return Bailout(kSuperReference);
   4257   }
   4258 
   4259   // Trace the call.
   4260   if (FLAG_trace && top_info()->IsOptimizing()) {
   4261     Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kTraceEnter), 0);
   4262   }
   4263 }
   4264 
   4265 
   4266 void HOptimizedGraphBuilder::VisitStatements(ZoneList<Statement*>* statements) {
   4267   for (int i = 0; i < statements->length(); i++) {
   4268     Statement* stmt = statements->at(i);
   4269     CHECK_ALIVE(Visit(stmt));
   4270     if (stmt->IsJump()) break;
   4271   }
   4272 }
   4273 
   4274 
   4275 void HOptimizedGraphBuilder::VisitBlock(Block* stmt) {
   4276   DCHECK(!HasStackOverflow());
   4277   DCHECK(current_block() != NULL);
   4278   DCHECK(current_block()->HasPredecessor());
   4279 
   4280   Scope* outer_scope = scope();
   4281   Scope* scope = stmt->scope();
   4282   BreakAndContinueInfo break_info(stmt, outer_scope);
   4283 
   4284   { BreakAndContinueScope push(&break_info, this);
   4285     if (scope != NULL) {
   4286       if (scope->NeedsContext()) {
   4287         // Load the function object.
   4288         DeclarationScope* declaration_scope = scope->GetDeclarationScope();
   4289         HInstruction* function;
   4290         HValue* outer_context = environment()->context();
   4291         if (declaration_scope->is_script_scope() ||
   4292             declaration_scope->is_eval_scope()) {
   4293           function = new (zone())
   4294               HLoadContextSlot(outer_context, Context::CLOSURE_INDEX,
   4295                                HLoadContextSlot::kNoCheck);
   4296         } else {
   4297           function = New<HThisFunction>();
   4298         }
   4299         AddInstruction(function);
   4300         // Allocate a block context and store it to the stack frame.
   4301         HValue* scope_info = Add<HConstant>(scope->scope_info());
   4302         Add<HPushArguments>(scope_info, function);
   4303         HInstruction* inner_context = Add<HCallRuntime>(
   4304             Runtime::FunctionForId(Runtime::kPushBlockContext), 2);
   4305         inner_context->SetFlag(HValue::kHasNoObservableSideEffects);
   4306         set_scope(scope);
   4307         environment()->BindContext(inner_context);
   4308       }
   4309       VisitDeclarations(scope->declarations());
   4310       AddSimulate(stmt->DeclsId(), REMOVABLE_SIMULATE);
   4311     }
   4312     CHECK_BAILOUT(VisitStatements(stmt->statements()));
   4313   }
   4314   set_scope(outer_scope);
   4315   if (scope != NULL && current_block() != NULL &&
   4316       scope->ContextLocalCount() > 0) {
   4317     HValue* inner_context = environment()->context();
   4318     HValue* outer_context = Add<HLoadNamedField>(
   4319         inner_context, nullptr,
   4320         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4321 
   4322     environment()->BindContext(outer_context);
   4323   }
   4324   HBasicBlock* break_block = break_info.break_block();
   4325   if (break_block != NULL) {
   4326     if (current_block() != NULL) Goto(break_block);
   4327     break_block->SetJoinId(stmt->ExitId());
   4328     set_current_block(break_block);
   4329   }
   4330 }
   4331 
   4332 
   4333 void HOptimizedGraphBuilder::VisitExpressionStatement(
   4334     ExpressionStatement* stmt) {
   4335   DCHECK(!HasStackOverflow());
   4336   DCHECK(current_block() != NULL);
   4337   DCHECK(current_block()->HasPredecessor());
   4338   VisitForEffect(stmt->expression());
   4339 }
   4340 
   4341 
   4342 void HOptimizedGraphBuilder::VisitEmptyStatement(EmptyStatement* stmt) {
   4343   DCHECK(!HasStackOverflow());
   4344   DCHECK(current_block() != NULL);
   4345   DCHECK(current_block()->HasPredecessor());
   4346 }
   4347 
   4348 
   4349 void HOptimizedGraphBuilder::VisitSloppyBlockFunctionStatement(
   4350     SloppyBlockFunctionStatement* stmt) {
   4351   Visit(stmt->statement());
   4352 }
   4353 
   4354 
   4355 void HOptimizedGraphBuilder::VisitIfStatement(IfStatement* stmt) {
   4356   DCHECK(!HasStackOverflow());
   4357   DCHECK(current_block() != NULL);
   4358   DCHECK(current_block()->HasPredecessor());
   4359   if (stmt->condition()->ToBooleanIsTrue()) {
   4360     Add<HSimulate>(stmt->ThenId());
   4361     Visit(stmt->then_statement());
   4362   } else if (stmt->condition()->ToBooleanIsFalse()) {
   4363     Add<HSimulate>(stmt->ElseId());
   4364     Visit(stmt->else_statement());
   4365   } else {
   4366     HBasicBlock* cond_true = graph()->CreateBasicBlock();
   4367     HBasicBlock* cond_false = graph()->CreateBasicBlock();
   4368     CHECK_BAILOUT(VisitForControl(stmt->condition(), cond_true, cond_false));
   4369 
   4370     // Technically, we should be able to handle the case when one side of
   4371     // the test is not connected, but this can trip up liveness analysis
   4372     // if we did not fully connect the test context based on some optimistic
   4373     // assumption. If such an assumption was violated, we would end up with
   4374     // an environment with optimized-out values. So we should always
   4375     // conservatively connect the test context.
   4376     CHECK(cond_true->HasPredecessor());
   4377     CHECK(cond_false->HasPredecessor());
   4378 
   4379     cond_true->SetJoinId(stmt->ThenId());
   4380     set_current_block(cond_true);
   4381     CHECK_BAILOUT(Visit(stmt->then_statement()));
   4382     cond_true = current_block();
   4383 
   4384     cond_false->SetJoinId(stmt->ElseId());
   4385     set_current_block(cond_false);
   4386     CHECK_BAILOUT(Visit(stmt->else_statement()));
   4387     cond_false = current_block();
   4388 
   4389     HBasicBlock* join = CreateJoin(cond_true, cond_false, stmt->IfId());
   4390     set_current_block(join);
   4391   }
   4392 }
   4393 
   4394 
   4395 HBasicBlock* HOptimizedGraphBuilder::BreakAndContinueScope::Get(
   4396     BreakableStatement* stmt,
   4397     BreakType type,
   4398     Scope** scope,
   4399     int* drop_extra) {
   4400   *drop_extra = 0;
   4401   BreakAndContinueScope* current = this;
   4402   while (current != NULL && current->info()->target() != stmt) {
   4403     *drop_extra += current->info()->drop_extra();
   4404     current = current->next();
   4405   }
   4406   DCHECK(current != NULL);  // Always found (unless stack is malformed).
   4407   *scope = current->info()->scope();
   4408 
   4409   if (type == BREAK) {
   4410     *drop_extra += current->info()->drop_extra();
   4411   }
   4412 
   4413   HBasicBlock* block = NULL;
   4414   switch (type) {
   4415     case BREAK:
   4416       block = current->info()->break_block();
   4417       if (block == NULL) {
   4418         block = current->owner()->graph()->CreateBasicBlock();
   4419         current->info()->set_break_block(block);
   4420       }
   4421       break;
   4422 
   4423     case CONTINUE:
   4424       block = current->info()->continue_block();
   4425       if (block == NULL) {
   4426         block = current->owner()->graph()->CreateBasicBlock();
   4427         current->info()->set_continue_block(block);
   4428       }
   4429       break;
   4430   }
   4431 
   4432   return block;
   4433 }
   4434 
   4435 
   4436 void HOptimizedGraphBuilder::VisitContinueStatement(
   4437     ContinueStatement* stmt) {
   4438   DCHECK(!HasStackOverflow());
   4439   DCHECK(current_block() != NULL);
   4440   DCHECK(current_block()->HasPredecessor());
   4441 
   4442   if (function_state()->IsInsideDoExpressionScope()) {
   4443     return Bailout(kDoExpressionUnmodelable);
   4444   }
   4445 
   4446   Scope* outer_scope = NULL;
   4447   Scope* inner_scope = scope();
   4448   int drop_extra = 0;
   4449   HBasicBlock* continue_block = break_scope()->Get(
   4450       stmt->target(), BreakAndContinueScope::CONTINUE,
   4451       &outer_scope, &drop_extra);
   4452   HValue* context = environment()->context();
   4453   Drop(drop_extra);
   4454   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
   4455   if (context_pop_count > 0) {
   4456     while (context_pop_count-- > 0) {
   4457       HInstruction* context_instruction = Add<HLoadNamedField>(
   4458           context, nullptr,
   4459           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4460       context = context_instruction;
   4461     }
   4462     environment()->BindContext(context);
   4463   }
   4464 
   4465   Goto(continue_block);
   4466   set_current_block(NULL);
   4467 }
   4468 
   4469 
   4470 void HOptimizedGraphBuilder::VisitBreakStatement(BreakStatement* stmt) {
   4471   DCHECK(!HasStackOverflow());
   4472   DCHECK(current_block() != NULL);
   4473   DCHECK(current_block()->HasPredecessor());
   4474 
   4475   if (function_state()->IsInsideDoExpressionScope()) {
   4476     return Bailout(kDoExpressionUnmodelable);
   4477   }
   4478 
   4479   Scope* outer_scope = NULL;
   4480   Scope* inner_scope = scope();
   4481   int drop_extra = 0;
   4482   HBasicBlock* break_block = break_scope()->Get(
   4483       stmt->target(), BreakAndContinueScope::BREAK,
   4484       &outer_scope, &drop_extra);
   4485   HValue* context = environment()->context();
   4486   Drop(drop_extra);
   4487   int context_pop_count = inner_scope->ContextChainLength(outer_scope);
   4488   if (context_pop_count > 0) {
   4489     while (context_pop_count-- > 0) {
   4490       HInstruction* context_instruction = Add<HLoadNamedField>(
   4491           context, nullptr,
   4492           HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   4493       context = context_instruction;
   4494     }
   4495     environment()->BindContext(context);
   4496   }
   4497   Goto(break_block);
   4498   set_current_block(NULL);
   4499 }
   4500 
   4501 
   4502 void HOptimizedGraphBuilder::VisitReturnStatement(ReturnStatement* stmt) {
   4503   DCHECK(!HasStackOverflow());
   4504   DCHECK(current_block() != NULL);
   4505   DCHECK(current_block()->HasPredecessor());
   4506   FunctionState* state = function_state();
   4507   AstContext* context = call_context();
   4508   if (context == NULL) {
   4509     // Not an inlined return, so an actual one.
   4510     CHECK_ALIVE(VisitForValue(stmt->expression()));
   4511     HValue* result = environment()->Pop();
   4512     Add<HReturn>(result);
   4513   } else if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
   4514     // Return from an inlined construct call. In a test context the return value
   4515     // will always evaluate to true, in a value context the return value needs
   4516     // to be a JSObject.
   4517     if (context->IsTest()) {
   4518       CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4519       context->ReturnValue(graph()->GetConstantTrue());
   4520     } else if (context->IsEffect()) {
   4521       CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4522       Goto(function_return(), state);
   4523     } else {
   4524       DCHECK(context->IsValue());
   4525       CHECK_ALIVE(VisitForValue(stmt->expression()));
   4526       HValue* return_value = Pop();
   4527       HValue* receiver = environment()->arguments_environment()->Lookup(0);
   4528       HHasInstanceTypeAndBranch* typecheck =
   4529           New<HHasInstanceTypeAndBranch>(return_value,
   4530                                          FIRST_JS_RECEIVER_TYPE,
   4531                                          LAST_JS_RECEIVER_TYPE);
   4532       HBasicBlock* if_spec_object = graph()->CreateBasicBlock();
   4533       HBasicBlock* not_spec_object = graph()->CreateBasicBlock();
   4534       typecheck->SetSuccessorAt(0, if_spec_object);
   4535       typecheck->SetSuccessorAt(1, not_spec_object);
   4536       FinishCurrentBlock(typecheck);
   4537       AddLeaveInlined(if_spec_object, return_value, state);
   4538       AddLeaveInlined(not_spec_object, receiver, state);
   4539     }
   4540   } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
   4541     // Return from an inlined setter call. The returned value is never used, the
   4542     // value of an assignment is always the value of the RHS of the assignment.
   4543     CHECK_ALIVE(VisitForEffect(stmt->expression()));
   4544     if (context->IsTest()) {
   4545       HValue* rhs = environment()->arguments_environment()->Lookup(1);
   4546       context->ReturnValue(rhs);
   4547     } else if (context->IsEffect()) {
   4548       Goto(function_return(), state);
   4549     } else {
   4550       DCHECK(context->IsValue());
   4551       HValue* rhs = environment()->arguments_environment()->Lookup(1);
   4552       AddLeaveInlined(rhs, state);
   4553     }
   4554   } else {
   4555     // Return from a normal inlined function. Visit the subexpression in the
   4556     // expression context of the call.
   4557     if (context->IsTest()) {
   4558       TestContext* test = TestContext::cast(context);
   4559       VisitForControl(stmt->expression(), test->if_true(), test->if_false());
   4560     } else if (context->IsEffect()) {
   4561       // Visit in value context and ignore the result. This is needed to keep
   4562       // environment in sync with full-codegen since some visitors (e.g.
   4563       // VisitCountOperation) use the operand stack differently depending on
   4564       // context.
   4565       CHECK_ALIVE(VisitForValue(stmt->expression()));
   4566       Pop();
   4567       Goto(function_return(), state);
   4568     } else {
   4569       DCHECK(context->IsValue());
   4570       CHECK_ALIVE(VisitForValue(stmt->expression()));
   4571       AddLeaveInlined(Pop(), state);
   4572     }
   4573   }
   4574   set_current_block(NULL);
   4575 }
   4576 
   4577 
   4578 void HOptimizedGraphBuilder::VisitWithStatement(WithStatement* stmt) {
   4579   DCHECK(!HasStackOverflow());
   4580   DCHECK(current_block() != NULL);
   4581   DCHECK(current_block()->HasPredecessor());
   4582   return Bailout(kWithStatement);
   4583 }
   4584 
   4585 
   4586 void HOptimizedGraphBuilder::VisitSwitchStatement(SwitchStatement* stmt) {
   4587   DCHECK(!HasStackOverflow());
   4588   DCHECK(current_block() != NULL);
   4589   DCHECK(current_block()->HasPredecessor());
   4590 
   4591   ZoneList<CaseClause*>* clauses = stmt->cases();
   4592   int clause_count = clauses->length();
   4593   ZoneList<HBasicBlock*> body_blocks(clause_count, zone());
   4594 
   4595   CHECK_ALIVE(VisitForValue(stmt->tag()));
   4596   Add<HSimulate>(stmt->EntryId());
   4597   HValue* tag_value = Top();
   4598   AstType* tag_type = bounds_.get(stmt->tag()).lower;
   4599 
   4600   // 1. Build all the tests, with dangling true branches
   4601   BailoutId default_id = BailoutId::None();
   4602   for (int i = 0; i < clause_count; ++i) {
   4603     CaseClause* clause = clauses->at(i);
   4604     if (clause->is_default()) {
   4605       body_blocks.Add(NULL, zone());
   4606       if (default_id.IsNone()) default_id = clause->EntryId();
   4607       continue;
   4608     }
   4609 
   4610     // Generate a compare and branch.
   4611     CHECK_BAILOUT(VisitForValue(clause->label()));
   4612     if (current_block() == NULL) return Bailout(kUnsupportedSwitchStatement);
   4613     HValue* label_value = Pop();
   4614 
   4615     AstType* label_type = bounds_.get(clause->label()).lower;
   4616     AstType* combined_type = clause->compare_type();
   4617     HControlInstruction* compare = BuildCompareInstruction(
   4618         Token::EQ_STRICT, tag_value, label_value, tag_type, label_type,
   4619         combined_type,
   4620         ScriptPositionToSourcePosition(stmt->tag()->position()),
   4621         ScriptPositionToSourcePosition(clause->label()->position()),
   4622         PUSH_BEFORE_SIMULATE, clause->id());
   4623 
   4624     HBasicBlock* next_test_block = graph()->CreateBasicBlock();
   4625     HBasicBlock* body_block = graph()->CreateBasicBlock();
   4626     body_blocks.Add(body_block, zone());
   4627     compare->SetSuccessorAt(0, body_block);
   4628     compare->SetSuccessorAt(1, next_test_block);
   4629     FinishCurrentBlock(compare);
   4630 
   4631     set_current_block(body_block);
   4632     Drop(1);  // tag_value
   4633 
   4634     set_current_block(next_test_block);
   4635   }
   4636 
   4637   // Save the current block to use for the default or to join with the
   4638   // exit.
   4639   HBasicBlock* last_block = current_block();
   4640   Drop(1);  // tag_value
   4641 
   4642   // 2. Loop over the clauses and the linked list of tests in lockstep,
   4643   // translating the clause bodies.
   4644   HBasicBlock* fall_through_block = NULL;
   4645 
   4646   BreakAndContinueInfo break_info(stmt, scope());
   4647   { BreakAndContinueScope push(&break_info, this);
   4648     for (int i = 0; i < clause_count; ++i) {
   4649       CaseClause* clause = clauses->at(i);
   4650 
   4651       // Identify the block where normal (non-fall-through) control flow
   4652       // goes to.
   4653       HBasicBlock* normal_block = NULL;
   4654       if (clause->is_default()) {
   4655         if (last_block == NULL) continue;
   4656         normal_block = last_block;
   4657         last_block = NULL;  // Cleared to indicate we've handled it.
   4658       } else {
   4659         normal_block = body_blocks[i];
   4660       }
   4661 
   4662       if (fall_through_block == NULL) {
   4663         set_current_block(normal_block);
   4664       } else {
   4665         HBasicBlock* join = CreateJoin(fall_through_block,
   4666                                        normal_block,
   4667                                        clause->EntryId());
   4668         set_current_block(join);
   4669       }
   4670 
   4671       CHECK_BAILOUT(VisitStatements(clause->statements()));
   4672       fall_through_block = current_block();
   4673     }
   4674   }
   4675 
   4676   // Create an up-to-3-way join.  Use the break block if it exists since
   4677   // it's already a join block.
   4678   HBasicBlock* break_block = break_info.break_block();
   4679   if (break_block == NULL) {
   4680     set_current_block(CreateJoin(fall_through_block,
   4681                                  last_block,
   4682                                  stmt->ExitId()));
   4683   } else {
   4684     if (fall_through_block != NULL) Goto(fall_through_block, break_block);
   4685     if (last_block != NULL) Goto(last_block, break_block);
   4686     break_block->SetJoinId(stmt->ExitId());
   4687     set_current_block(break_block);
   4688   }
   4689 }
   4690 
   4691 void HOptimizedGraphBuilder::VisitLoopBody(IterationStatement* stmt,
   4692                                            BailoutId stack_check_id,
   4693                                            HBasicBlock* loop_entry) {
   4694   Add<HSimulate>(stack_check_id);
   4695   HStackCheck* stack_check =
   4696       HStackCheck::cast(Add<HStackCheck>(HStackCheck::kBackwardsBranch));
   4697   DCHECK(loop_entry->IsLoopHeader());
   4698   loop_entry->loop_information()->set_stack_check(stack_check);
   4699   CHECK_BAILOUT(Visit(stmt->body()));
   4700 }
   4701 
   4702 
   4703 void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
   4704   DCHECK(!HasStackOverflow());
   4705   DCHECK(current_block() != NULL);
   4706   DCHECK(current_block()->HasPredecessor());
   4707   DCHECK(current_block() != NULL);
   4708   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   4709 
   4710   BreakAndContinueInfo break_info(stmt, scope());
   4711   {
   4712     BreakAndContinueScope push(&break_info, this);
   4713     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
   4714   }
   4715   HBasicBlock* body_exit = JoinContinue(
   4716       stmt, stmt->ContinueId(), current_block(), break_info.continue_block());
   4717   HBasicBlock* loop_successor = NULL;
   4718   if (body_exit != NULL) {
   4719     set_current_block(body_exit);
   4720     loop_successor = graph()->CreateBasicBlock();
   4721     if (stmt->cond()->ToBooleanIsFalse()) {
   4722       loop_entry->loop_information()->stack_check()->Eliminate();
   4723       Goto(loop_successor);
   4724       body_exit = NULL;
   4725     } else {
   4726       // The block for a true condition, the actual predecessor block of the
   4727       // back edge.
   4728       body_exit = graph()->CreateBasicBlock();
   4729       CHECK_BAILOUT(VisitForControl(stmt->cond(), body_exit, loop_successor));
   4730     }
   4731     if (body_exit != NULL && body_exit->HasPredecessor()) {
   4732       body_exit->SetJoinId(stmt->BackEdgeId());
   4733     } else {
   4734       body_exit = NULL;
   4735     }
   4736     if (loop_successor->HasPredecessor()) {
   4737       loop_successor->SetJoinId(stmt->ExitId());
   4738     } else {
   4739       loop_successor = NULL;
   4740     }
   4741   }
   4742   HBasicBlock* loop_exit = CreateLoop(stmt,
   4743                                       loop_entry,
   4744                                       body_exit,
   4745                                       loop_successor,
   4746                                       break_info.break_block());
   4747   set_current_block(loop_exit);
   4748 }
   4749 
   4750 
   4751 void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
   4752   DCHECK(!HasStackOverflow());
   4753   DCHECK(current_block() != NULL);
   4754   DCHECK(current_block()->HasPredecessor());
   4755   DCHECK(current_block() != NULL);
   4756   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   4757 
   4758   // If the condition is constant true, do not generate a branch.
   4759   HBasicBlock* loop_successor = NULL;
   4760   HBasicBlock* body_entry = graph()->CreateBasicBlock();
   4761   loop_successor = graph()->CreateBasicBlock();
   4762   CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
   4763   if (body_entry->HasPredecessor()) {
   4764     body_entry->SetJoinId(stmt->BodyId());
   4765     set_current_block(body_entry);
   4766   }
   4767   if (loop_successor->HasPredecessor()) {
   4768     loop_successor->SetJoinId(stmt->ExitId());
   4769   } else {
   4770     loop_successor = NULL;
   4771   }
   4772 
   4773   BreakAndContinueInfo break_info(stmt, scope());
   4774   if (current_block() != NULL) {
   4775     BreakAndContinueScope push(&break_info, this);
   4776     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
   4777   }
   4778   HBasicBlock* body_exit = JoinContinue(
   4779       stmt, stmt->ContinueId(), current_block(), break_info.continue_block());
   4780   HBasicBlock* loop_exit = CreateLoop(stmt,
   4781                                       loop_entry,
   4782                                       body_exit,
   4783                                       loop_successor,
   4784                                       break_info.break_block());
   4785   set_current_block(loop_exit);
   4786 }
   4787 
   4788 
   4789 void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
   4790   DCHECK(!HasStackOverflow());
   4791   DCHECK(current_block() != NULL);
   4792   DCHECK(current_block()->HasPredecessor());
   4793   if (stmt->init() != NULL) {
   4794     CHECK_ALIVE(Visit(stmt->init()));
   4795   }
   4796   DCHECK(current_block() != NULL);
   4797   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   4798 
   4799   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
   4800   HBasicBlock* body_entry = graph()->CreateBasicBlock();
   4801   if (stmt->cond() != NULL) {
   4802     CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
   4803     if (body_entry->HasPredecessor()) {
   4804       body_entry->SetJoinId(stmt->BodyId());
   4805       set_current_block(body_entry);
   4806     }
   4807     if (loop_successor->HasPredecessor()) {
   4808       loop_successor->SetJoinId(stmt->ExitId());
   4809     } else {
   4810       loop_successor = NULL;
   4811     }
   4812   } else {
   4813     // Create dummy control flow so that variable liveness analysis
   4814     // produces teh correct result.
   4815     HControlInstruction* branch = New<HBranch>(graph()->GetConstantTrue());
   4816     branch->SetSuccessorAt(0, body_entry);
   4817     branch->SetSuccessorAt(1, loop_successor);
   4818     FinishCurrentBlock(branch);
   4819     set_current_block(body_entry);
   4820   }
   4821 
   4822   BreakAndContinueInfo break_info(stmt, scope());
   4823   if (current_block() != NULL) {
   4824     BreakAndContinueScope push(&break_info, this);
   4825     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
   4826   }
   4827   HBasicBlock* body_exit = JoinContinue(
   4828       stmt, stmt->ContinueId(), current_block(), break_info.continue_block());
   4829 
   4830   if (stmt->next() != NULL && body_exit != NULL) {
   4831     set_current_block(body_exit);
   4832     CHECK_BAILOUT(Visit(stmt->next()));
   4833     body_exit = current_block();
   4834   }
   4835 
   4836   HBasicBlock* loop_exit = CreateLoop(stmt,
   4837                                       loop_entry,
   4838                                       body_exit,
   4839                                       loop_successor,
   4840                                       break_info.break_block());
   4841   set_current_block(loop_exit);
   4842 }
   4843 
   4844 
   4845 void HOptimizedGraphBuilder::VisitForInStatement(ForInStatement* stmt) {
   4846   DCHECK(!HasStackOverflow());
   4847   DCHECK(current_block() != NULL);
   4848   DCHECK(current_block()->HasPredecessor());
   4849 
   4850   if (!stmt->each()->IsVariableProxy() ||
   4851       !stmt->each()->AsVariableProxy()->var()->IsStackLocal()) {
   4852     return Bailout(kForInStatementWithNonLocalEachVariable);
   4853   }
   4854 
   4855   Variable* each_var = stmt->each()->AsVariableProxy()->var();
   4856 
   4857   CHECK_ALIVE(VisitForValue(stmt->enumerable()));
   4858   HValue* enumerable = Top();  // Leave enumerable at the top.
   4859 
   4860   IfBuilder if_undefined_or_null(this);
   4861   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
   4862       enumerable, graph()->GetConstantUndefined());
   4863   if_undefined_or_null.Or();
   4864   if_undefined_or_null.If<HCompareObjectEqAndBranch>(
   4865       enumerable, graph()->GetConstantNull());
   4866   if_undefined_or_null.ThenDeopt(DeoptimizeReason::kUndefinedOrNullInForIn);
   4867   if_undefined_or_null.End();
   4868   BuildForInBody(stmt, each_var, enumerable);
   4869 }
   4870 
   4871 
   4872 void HOptimizedGraphBuilder::BuildForInBody(ForInStatement* stmt,
   4873                                             Variable* each_var,
   4874                                             HValue* enumerable) {
   4875   Handle<Map> meta_map = isolate()->factory()->meta_map();
   4876   bool fast = stmt->for_in_type() == ForInStatement::FAST_FOR_IN;
   4877   BuildCheckHeapObject(enumerable);
   4878   Add<HCheckInstanceType>(enumerable, HCheckInstanceType::IS_JS_RECEIVER);
   4879   Add<HSimulate>(stmt->ToObjectId());
   4880   if (fast) {
   4881     HForInPrepareMap* map = Add<HForInPrepareMap>(enumerable);
   4882     Push(map);
   4883     Add<HSimulate>(stmt->EnumId());
   4884     Drop(1);
   4885     Add<HCheckMaps>(map, meta_map);
   4886 
   4887     HForInCacheArray* array = Add<HForInCacheArray>(
   4888         enumerable, map, DescriptorArray::kEnumCacheBridgeCacheIndex);
   4889     HValue* enum_length = BuildEnumLength(map);
   4890 
   4891     HForInCacheArray* index_cache = Add<HForInCacheArray>(
   4892         enumerable, map, DescriptorArray::kEnumCacheBridgeIndicesCacheIndex);
   4893     array->set_index_cache(index_cache);
   4894 
   4895     Push(map);
   4896     Push(array);
   4897     Push(enum_length);
   4898     Add<HSimulate>(stmt->PrepareId());
   4899   } else {
   4900     Runtime::FunctionId function_id = Runtime::kForInEnumerate;
   4901     Add<HPushArguments>(enumerable);
   4902     HCallRuntime* array =
   4903         Add<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
   4904     Push(array);
   4905     Add<HSimulate>(stmt->EnumId());
   4906     Drop(1);
   4907 
   4908     IfBuilder if_fast(this);
   4909     if_fast.If<HCompareMap>(array, meta_map);
   4910     if_fast.Then();
   4911     {
   4912       HValue* cache_map = array;
   4913       HForInCacheArray* cache = Add<HForInCacheArray>(
   4914           enumerable, cache_map, DescriptorArray::kEnumCacheBridgeCacheIndex);
   4915       HValue* enum_length = BuildEnumLength(cache_map);
   4916       Push(cache_map);
   4917       Push(cache);
   4918       Push(enum_length);
   4919       Add<HSimulate>(stmt->PrepareId(), FIXED_SIMULATE);
   4920     }
   4921     if_fast.Else();
   4922     {
   4923       Push(graph()->GetConstant1());
   4924       Push(array);
   4925       Push(AddLoadFixedArrayLength(array));
   4926       Add<HSimulate>(stmt->PrepareId(), FIXED_SIMULATE);
   4927     }
   4928   }
   4929 
   4930   Push(graph()->GetConstant0());
   4931 
   4932   HBasicBlock* loop_entry = BuildLoopEntry(stmt);
   4933 
   4934   // Reload the values to ensure we have up-to-date values inside of the loop.
   4935   // This is relevant especially for OSR where the values don't come from the
   4936   // computation above, but from the OSR entry block.
   4937   HValue* index = environment()->ExpressionStackAt(0);
   4938   HValue* limit = environment()->ExpressionStackAt(1);
   4939   HValue* array = environment()->ExpressionStackAt(2);
   4940   HValue* type = environment()->ExpressionStackAt(3);
   4941   enumerable = environment()->ExpressionStackAt(4);
   4942 
   4943   // Check that we still have more keys.
   4944   HCompareNumericAndBranch* compare_index =
   4945       New<HCompareNumericAndBranch>(index, limit, Token::LT);
   4946   compare_index->set_observed_input_representation(
   4947       Representation::Smi(), Representation::Smi());
   4948 
   4949   HBasicBlock* loop_body = graph()->CreateBasicBlock();
   4950   HBasicBlock* loop_successor = graph()->CreateBasicBlock();
   4951 
   4952   compare_index->SetSuccessorAt(0, loop_body);
   4953   compare_index->SetSuccessorAt(1, loop_successor);
   4954   FinishCurrentBlock(compare_index);
   4955 
   4956   set_current_block(loop_successor);
   4957   Drop(5);
   4958 
   4959   set_current_block(loop_body);
   4960 
   4961   // Compute the next enumerated value.
   4962   HValue* key = Add<HLoadKeyed>(array, index, index, nullptr, FAST_ELEMENTS);
   4963 
   4964   HBasicBlock* continue_block = nullptr;
   4965   if (fast) {
   4966     // Check if expected map still matches that of the enumerable.
   4967     Add<HCheckMapValue>(enumerable, type);
   4968     Add<HSimulate>(stmt->FilterId());
   4969   } else {
   4970     // We need the continue block here to be able to skip over invalidated keys.
   4971     continue_block = graph()->CreateBasicBlock();
   4972 
   4973     // We cannot use the IfBuilder here, since we need to be able to jump
   4974     // over the loop body in case of undefined result from %ForInFilter,
   4975     // and the poor soul that is the IfBuilder get's really confused about
   4976     // such "advanced control flow requirements".
   4977     HBasicBlock* if_fast = graph()->CreateBasicBlock();
   4978     HBasicBlock* if_slow = graph()->CreateBasicBlock();
   4979     HBasicBlock* if_slow_pass = graph()->CreateBasicBlock();
   4980     HBasicBlock* if_slow_skip = graph()->CreateBasicBlock();
   4981     HBasicBlock* if_join = graph()->CreateBasicBlock();
   4982 
   4983     // Check if expected map still matches that of the enumerable.
   4984     HValue* enumerable_map =
   4985         Add<HLoadNamedField>(enumerable, nullptr, HObjectAccess::ForMap());
   4986     FinishCurrentBlock(
   4987         New<HCompareObjectEqAndBranch>(enumerable_map, type, if_fast, if_slow));
   4988     set_current_block(if_fast);
   4989     {
   4990       // The enum cache for enumerable is still valid, no need to check key.
   4991       Push(key);
   4992       Goto(if_join);
   4993     }
   4994     set_current_block(if_slow);
   4995     {
   4996       Callable callable = CodeFactory::ForInFilter(isolate());
   4997       HValue* values[] = {key, enumerable};
   4998       HConstant* stub_value = Add<HConstant>(callable.code());
   4999       Push(Add<HCallWithDescriptor>(stub_value, 0, callable.descriptor(),
   5000                                     ArrayVector(values)));
   5001       Add<HSimulate>(stmt->FilterId());
   5002       FinishCurrentBlock(New<HCompareObjectEqAndBranch>(
   5003           Top(), graph()->GetConstantUndefined(), if_slow_skip, if_slow_pass));
   5004     }
   5005     set_current_block(if_slow_pass);
   5006     { Goto(if_join); }
   5007     set_current_block(if_slow_skip);
   5008     {
   5009       // The key is no longer valid for enumerable, skip it.
   5010       Drop(1);
   5011       Goto(continue_block);
   5012     }
   5013     if_join->SetJoinId(stmt->FilterId());
   5014     set_current_block(if_join);
   5015     key = Pop();
   5016   }
   5017 
   5018   Bind(each_var, key);
   5019   Add<HSimulate>(stmt->AssignmentId());
   5020 
   5021   BreakAndContinueInfo break_info(stmt, scope(), 5);
   5022   break_info.set_continue_block(continue_block);
   5023   {
   5024     BreakAndContinueScope push(&break_info, this);
   5025     CHECK_BAILOUT(VisitLoopBody(stmt, stmt->StackCheckId(), loop_entry));
   5026   }
   5027 
   5028   HBasicBlock* body_exit = JoinContinue(
   5029       stmt, stmt->IncrementId(), current_block(), break_info.continue_block());
   5030 
   5031   if (body_exit != NULL) {
   5032     set_current_block(body_exit);
   5033 
   5034     HValue* current_index = Pop();
   5035     HValue* increment =
   5036         AddUncasted<HAdd>(current_index, graph()->GetConstant1());
   5037     increment->ClearFlag(HValue::kCanOverflow);
   5038     Push(increment);
   5039     body_exit = current_block();
   5040   }
   5041 
   5042   HBasicBlock* loop_exit = CreateLoop(stmt,
   5043                                       loop_entry,
   5044                                       body_exit,
   5045                                       loop_successor,
   5046                                       break_info.break_block());
   5047 
   5048   set_current_block(loop_exit);
   5049 }
   5050 
   5051 
   5052 void HOptimizedGraphBuilder::VisitForOfStatement(ForOfStatement* stmt) {
   5053   DCHECK(!HasStackOverflow());
   5054   DCHECK(current_block() != NULL);
   5055   DCHECK(current_block()->HasPredecessor());
   5056   return Bailout(kForOfStatement);
   5057 }
   5058 
   5059 
   5060 void HOptimizedGraphBuilder::VisitTryCatchStatement(TryCatchStatement* stmt) {
   5061   DCHECK(!HasStackOverflow());
   5062   DCHECK(current_block() != NULL);
   5063   DCHECK(current_block()->HasPredecessor());
   5064   return Bailout(kTryCatchStatement);
   5065 }
   5066 
   5067 
   5068 void HOptimizedGraphBuilder::VisitTryFinallyStatement(
   5069     TryFinallyStatement* stmt) {
   5070   DCHECK(!HasStackOverflow());
   5071   DCHECK(current_block() != NULL);
   5072   DCHECK(current_block()->HasPredecessor());
   5073   return Bailout(kTryFinallyStatement);
   5074 }
   5075 
   5076 
   5077 void HOptimizedGraphBuilder::VisitDebuggerStatement(DebuggerStatement* stmt) {
   5078   DCHECK(!HasStackOverflow());
   5079   DCHECK(current_block() != NULL);
   5080   DCHECK(current_block()->HasPredecessor());
   5081   return Bailout(kDebuggerStatement);
   5082 }
   5083 
   5084 
   5085 void HOptimizedGraphBuilder::VisitCaseClause(CaseClause* clause) {
   5086   UNREACHABLE();
   5087 }
   5088 
   5089 
   5090 void HOptimizedGraphBuilder::VisitFunctionLiteral(FunctionLiteral* expr) {
   5091   DCHECK(!HasStackOverflow());
   5092   DCHECK(current_block() != NULL);
   5093   DCHECK(current_block()->HasPredecessor());
   5094   Handle<SharedFunctionInfo> shared_info = Compiler::GetSharedFunctionInfo(
   5095       expr, current_info()->script(), top_info());
   5096   // We also have a stack overflow if the recursive compilation did.
   5097   if (HasStackOverflow()) return;
   5098   // Use the fast case closure allocation code that allocates in new
   5099   // space for nested functions that don't need pretenuring.
   5100   HConstant* shared_info_value = Add<HConstant>(shared_info);
   5101   HInstruction* instr;
   5102   if (!expr->pretenure()) {
   5103     FastNewClosureStub stub(isolate());
   5104     FastNewClosureDescriptor descriptor(isolate());
   5105     HValue* values[] = {shared_info_value};
   5106     HConstant* stub_value = Add<HConstant>(stub.GetCode());
   5107     instr = New<HCallWithDescriptor>(stub_value, 0, descriptor,
   5108                                      ArrayVector(values));
   5109   } else {
   5110     Add<HPushArguments>(shared_info_value);
   5111     Runtime::FunctionId function_id =
   5112         expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure;
   5113     instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 1);
   5114   }
   5115   return ast_context()->ReturnInstruction(instr, expr->id());
   5116 }
   5117 
   5118 
   5119 void HOptimizedGraphBuilder::VisitClassLiteral(ClassLiteral* lit) {
   5120   DCHECK(!HasStackOverflow());
   5121   DCHECK(current_block() != NULL);
   5122   DCHECK(current_block()->HasPredecessor());
   5123   return Bailout(kClassLiteral);
   5124 }
   5125 
   5126 
   5127 void HOptimizedGraphBuilder::VisitNativeFunctionLiteral(
   5128     NativeFunctionLiteral* expr) {
   5129   DCHECK(!HasStackOverflow());
   5130   DCHECK(current_block() != NULL);
   5131   DCHECK(current_block()->HasPredecessor());
   5132   return Bailout(kNativeFunctionLiteral);
   5133 }
   5134 
   5135 
   5136 void HOptimizedGraphBuilder::VisitDoExpression(DoExpression* expr) {
   5137   DoExpressionScope scope(this);
   5138   DCHECK(!HasStackOverflow());
   5139   DCHECK(current_block() != NULL);
   5140   DCHECK(current_block()->HasPredecessor());
   5141   CHECK_ALIVE(VisitBlock(expr->block()));
   5142   Visit(expr->result());
   5143 }
   5144 
   5145 
   5146 void HOptimizedGraphBuilder::VisitConditional(Conditional* expr) {
   5147   DCHECK(!HasStackOverflow());
   5148   DCHECK(current_block() != NULL);
   5149   DCHECK(current_block()->HasPredecessor());
   5150   HBasicBlock* cond_true = graph()->CreateBasicBlock();
   5151   HBasicBlock* cond_false = graph()->CreateBasicBlock();
   5152   CHECK_BAILOUT(VisitForControl(expr->condition(), cond_true, cond_false));
   5153 
   5154   // Visit the true and false subexpressions in the same AST context as the
   5155   // whole expression.
   5156   if (cond_true->HasPredecessor()) {
   5157     cond_true->SetJoinId(expr->ThenId());
   5158     set_current_block(cond_true);
   5159     CHECK_BAILOUT(Visit(expr->then_expression()));
   5160     cond_true = current_block();
   5161   } else {
   5162     cond_true = NULL;
   5163   }
   5164 
   5165   if (cond_false->HasPredecessor()) {
   5166     cond_false->SetJoinId(expr->ElseId());
   5167     set_current_block(cond_false);
   5168     CHECK_BAILOUT(Visit(expr->else_expression()));
   5169     cond_false = current_block();
   5170   } else {
   5171     cond_false = NULL;
   5172   }
   5173 
   5174   if (!ast_context()->IsTest()) {
   5175     HBasicBlock* join = CreateJoin(cond_true, cond_false, expr->id());
   5176     set_current_block(join);
   5177     if (join != NULL && !ast_context()->IsEffect()) {
   5178       return ast_context()->ReturnValue(Pop());
   5179     }
   5180   }
   5181 }
   5182 
   5183 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess(
   5184     Variable* var, LookupIterator* it, PropertyAccessType access_type) {
   5185   if (var->is_this()) return false;
   5186   return CanInlineGlobalPropertyAccess(it, access_type);
   5187 }
   5188 
   5189 bool HOptimizedGraphBuilder::CanInlineGlobalPropertyAccess(
   5190     LookupIterator* it, PropertyAccessType access_type) {
   5191   if (!current_info()->has_global_object()) {
   5192     return false;
   5193   }
   5194 
   5195   switch (it->state()) {
   5196     case LookupIterator::ACCESSOR:
   5197     case LookupIterator::ACCESS_CHECK:
   5198     case LookupIterator::INTERCEPTOR:
   5199     case LookupIterator::INTEGER_INDEXED_EXOTIC:
   5200     case LookupIterator::NOT_FOUND:
   5201       return false;
   5202     case LookupIterator::DATA:
   5203       if (access_type == STORE && it->IsReadOnly()) return false;
   5204       if (!it->GetHolder<JSObject>()->IsJSGlobalObject()) return false;
   5205       return true;
   5206     case LookupIterator::JSPROXY:
   5207     case LookupIterator::TRANSITION:
   5208       UNREACHABLE();
   5209   }
   5210   UNREACHABLE();
   5211   return false;
   5212 }
   5213 
   5214 
   5215 HValue* HOptimizedGraphBuilder::BuildContextChainWalk(Variable* var) {
   5216   DCHECK(var->IsContextSlot());
   5217   HValue* context = environment()->context();
   5218   int length = scope()->ContextChainLength(var->scope());
   5219   while (length-- > 0) {
   5220     context = Add<HLoadNamedField>(
   5221         context, nullptr,
   5222         HObjectAccess::ForContextSlot(Context::PREVIOUS_INDEX));
   5223   }
   5224   return context;
   5225 }
   5226 
   5227 void HOptimizedGraphBuilder::InlineGlobalPropertyLoad(LookupIterator* it,
   5228                                                       BailoutId ast_id) {
   5229   Handle<PropertyCell> cell = it->GetPropertyCell();
   5230   top_info()->dependencies()->AssumePropertyCell(cell);
   5231   auto cell_type = it->property_details().cell_type();
   5232   if (cell_type == PropertyCellType::kConstant ||
   5233       cell_type == PropertyCellType::kUndefined) {
   5234     Handle<Object> constant_object(cell->value(), isolate());
   5235     if (constant_object->IsConsString()) {
   5236       constant_object = String::Flatten(Handle<String>::cast(constant_object));
   5237     }
   5238     HConstant* constant = New<HConstant>(constant_object);
   5239     return ast_context()->ReturnInstruction(constant, ast_id);
   5240   } else {
   5241     auto access = HObjectAccess::ForPropertyCellValue();
   5242     UniqueSet<Map>* field_maps = nullptr;
   5243     if (cell_type == PropertyCellType::kConstantType) {
   5244       switch (cell->GetConstantType()) {
   5245         case PropertyCellConstantType::kSmi:
   5246           access = access.WithRepresentation(Representation::Smi());
   5247           break;
   5248         case PropertyCellConstantType::kStableMap: {
   5249           // Check that the map really is stable. The heap object could
   5250           // have mutated without the cell updating state. In that case,
   5251           // make no promises about the loaded value except that it's a
   5252           // heap object.
   5253           access = access.WithRepresentation(Representation::HeapObject());
   5254           Handle<Map> map(HeapObject::cast(cell->value())->map());
   5255           if (map->is_stable()) {
   5256             field_maps = new (zone())
   5257                 UniqueSet<Map>(Unique<Map>::CreateImmovable(map), zone());
   5258           }
   5259           break;
   5260         }
   5261       }
   5262     }
   5263     HConstant* cell_constant = Add<HConstant>(cell);
   5264     HLoadNamedField* instr;
   5265     if (field_maps == nullptr) {
   5266       instr = New<HLoadNamedField>(cell_constant, nullptr, access);
   5267     } else {
   5268       instr = New<HLoadNamedField>(cell_constant, nullptr, access, field_maps,
   5269                                    HType::HeapObject());
   5270     }
   5271     instr->ClearDependsOnFlag(kInobjectFields);
   5272     instr->SetDependsOnFlag(kGlobalVars);
   5273     return ast_context()->ReturnInstruction(instr, ast_id);
   5274   }
   5275 }
   5276 
   5277 void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
   5278   DCHECK(!HasStackOverflow());
   5279   DCHECK(current_block() != NULL);
   5280   DCHECK(current_block()->HasPredecessor());
   5281   Variable* variable = expr->var();
   5282   switch (variable->location()) {
   5283     case VariableLocation::UNALLOCATED: {
   5284       if (IsLexicalVariableMode(variable->mode())) {
   5285         // TODO(rossberg): should this be an DCHECK?
   5286         return Bailout(kReferenceToGlobalLexicalVariable);
   5287       }
   5288       // Handle known global constants like 'undefined' specially to avoid a
   5289       // load from a global cell for them.
   5290       Handle<Object> constant_value =
   5291           isolate()->factory()->GlobalConstantFor(variable->name());
   5292       if (!constant_value.is_null()) {
   5293         HConstant* instr = New<HConstant>(constant_value);
   5294         return ast_context()->ReturnInstruction(instr, expr->id());
   5295       }
   5296 
   5297       Handle<JSGlobalObject> global(current_info()->global_object());
   5298 
   5299       // Lookup in script contexts.
   5300       {
   5301         Handle<ScriptContextTable> script_contexts(
   5302             global->native_context()->script_context_table());
   5303         ScriptContextTable::LookupResult lookup;
   5304         if (ScriptContextTable::Lookup(script_contexts, variable->name(),
   5305                                        &lookup)) {
   5306           Handle<Context> script_context = ScriptContextTable::GetContext(
   5307               script_contexts, lookup.context_index);
   5308           Handle<Object> current_value =
   5309               FixedArray::get(*script_context, lookup.slot_index, isolate());
   5310 
   5311           // If the values is not the hole, it will stay initialized,
   5312           // so no need to generate a check.
   5313           if (current_value->IsTheHole(isolate())) {
   5314             return Bailout(kReferenceToUninitializedVariable);
   5315           }
   5316           HInstruction* result = New<HLoadNamedField>(
   5317               Add<HConstant>(script_context), nullptr,
   5318               HObjectAccess::ForContextSlot(lookup.slot_index));
   5319           return ast_context()->ReturnInstruction(result, expr->id());
   5320         }
   5321       }
   5322 
   5323       LookupIterator it(global, variable->name(), LookupIterator::OWN);
   5324       it.TryLookupCachedProperty();
   5325       if (CanInlineGlobalPropertyAccess(variable, &it, LOAD)) {
   5326         InlineGlobalPropertyLoad(&it, expr->id());
   5327         return;
   5328       } else {
   5329         Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate());
   5330 
   5331         HValue* vector_value = Add<HConstant>(vector);
   5332         HValue* slot_value =
   5333             Add<HConstant>(vector->GetIndex(expr->VariableFeedbackSlot()));
   5334         Callable callable = CodeFactory::LoadGlobalICInOptimizedCode(
   5335             isolate(), ast_context()->typeof_mode());
   5336         HValue* stub = Add<HConstant>(callable.code());
   5337         HValue* values[] = {slot_value, vector_value};
   5338         HCallWithDescriptor* instr = New<HCallWithDescriptor>(
   5339             Code::LOAD_GLOBAL_IC, stub, 0, callable.descriptor(),
   5340             ArrayVector(values));
   5341         return ast_context()->ReturnInstruction(instr, expr->id());
   5342       }
   5343     }
   5344 
   5345     case VariableLocation::PARAMETER:
   5346     case VariableLocation::LOCAL: {
   5347       HValue* value = LookupAndMakeLive(variable);
   5348       if (value == graph()->GetConstantHole()) {
   5349         DCHECK(IsDeclaredVariableMode(variable->mode()) &&
   5350                variable->mode() != VAR);
   5351         return Bailout(kReferenceToUninitializedVariable);
   5352       }
   5353       return ast_context()->ReturnValue(value);
   5354     }
   5355 
   5356     case VariableLocation::CONTEXT: {
   5357       HValue* context = BuildContextChainWalk(variable);
   5358       HLoadContextSlot::Mode mode;
   5359       switch (variable->mode()) {
   5360         case LET:
   5361         case CONST:
   5362           mode = HLoadContextSlot::kCheckDeoptimize;
   5363           break;
   5364         default:
   5365           mode = HLoadContextSlot::kNoCheck;
   5366           break;
   5367       }
   5368       HLoadContextSlot* instr =
   5369           new(zone()) HLoadContextSlot(context, variable->index(), mode);
   5370       return ast_context()->ReturnInstruction(instr, expr->id());
   5371     }
   5372 
   5373     case VariableLocation::LOOKUP:
   5374       return Bailout(kReferenceToAVariableWhichRequiresDynamicLookup);
   5375 
   5376     case VariableLocation::MODULE:
   5377       UNREACHABLE();
   5378   }
   5379 }
   5380 
   5381 
   5382 void HOptimizedGraphBuilder::VisitLiteral(Literal* expr) {
   5383   DCHECK(!HasStackOverflow());
   5384   DCHECK(current_block() != NULL);
   5385   DCHECK(current_block()->HasPredecessor());
   5386   HConstant* instr = New<HConstant>(expr->value());
   5387   return ast_context()->ReturnInstruction(instr, expr->id());
   5388 }
   5389 
   5390 
   5391 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
   5392   DCHECK(!HasStackOverflow());
   5393   DCHECK(current_block() != NULL);
   5394   DCHECK(current_block()->HasPredecessor());
   5395   Callable callable = CodeFactory::FastCloneRegExp(isolate());
   5396   HValue* values[] = {AddThisFunction(), Add<HConstant>(expr->literal_index()),
   5397                       Add<HConstant>(expr->pattern()),
   5398                       Add<HConstant>(expr->flags())};
   5399   HConstant* stub_value = Add<HConstant>(callable.code());
   5400   HInstruction* instr = New<HCallWithDescriptor>(
   5401       stub_value, 0, callable.descriptor(), ArrayVector(values));
   5402   return ast_context()->ReturnInstruction(instr, expr->id());
   5403 }
   5404 
   5405 
   5406 static bool CanInlinePropertyAccess(Handle<Map> map) {
   5407   if (map->instance_type() == HEAP_NUMBER_TYPE) return true;
   5408   if (map->instance_type() < FIRST_NONSTRING_TYPE) return true;
   5409   return map->IsJSObjectMap() && !map->is_dictionary_map() &&
   5410          !map->has_named_interceptor() &&
   5411          // TODO(verwaest): Whitelist contexts to which we have access.
   5412          !map->is_access_check_needed();
   5413 }
   5414 
   5415 
   5416 // Determines whether the given array or object literal boilerplate satisfies
   5417 // all limits to be considered for fast deep-copying and computes the total
   5418 // size of all objects that are part of the graph.
   5419 static bool IsFastLiteral(Handle<JSObject> boilerplate,
   5420                           int max_depth,
   5421                           int* max_properties) {
   5422   if (boilerplate->map()->is_deprecated() &&
   5423       !JSObject::TryMigrateInstance(boilerplate)) {
   5424     return false;
   5425   }
   5426 
   5427   DCHECK(max_depth >= 0 && *max_properties >= 0);
   5428   if (max_depth == 0) return false;
   5429 
   5430   Isolate* isolate = boilerplate->GetIsolate();
   5431   Handle<FixedArrayBase> elements(boilerplate->elements());
   5432   if (elements->length() > 0 &&
   5433       elements->map() != isolate->heap()->fixed_cow_array_map()) {
   5434     if (boilerplate->HasFastSmiOrObjectElements()) {
   5435       Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
   5436       int length = elements->length();
   5437       for (int i = 0; i < length; i++) {
   5438         if ((*max_properties)-- == 0) return false;
   5439         Handle<Object> value(fast_elements->get(i), isolate);
   5440         if (value->IsJSObject()) {
   5441           Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   5442           if (!IsFastLiteral(value_object,
   5443                              max_depth - 1,
   5444                              max_properties)) {
   5445             return false;
   5446           }
   5447         }
   5448       }
   5449     } else if (!boilerplate->HasFastDoubleElements()) {
   5450       return false;
   5451     }
   5452   }
   5453 
   5454   Handle<FixedArray> properties(boilerplate->properties());
   5455   if (properties->length() > 0) {
   5456     return false;
   5457   } else {
   5458     Handle<DescriptorArray> descriptors(
   5459         boilerplate->map()->instance_descriptors());
   5460     int limit = boilerplate->map()->NumberOfOwnDescriptors();
   5461     for (int i = 0; i < limit; i++) {
   5462       PropertyDetails details = descriptors->GetDetails(i);
   5463       if (details.type() != DATA) continue;
   5464       if ((*max_properties)-- == 0) return false;
   5465       FieldIndex field_index = FieldIndex::ForDescriptor(boilerplate->map(), i);
   5466       if (boilerplate->IsUnboxedDoubleField(field_index)) continue;
   5467       Handle<Object> value(boilerplate->RawFastPropertyAt(field_index),
   5468                            isolate);
   5469       if (value->IsJSObject()) {
   5470         Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   5471         if (!IsFastLiteral(value_object,
   5472                            max_depth - 1,
   5473                            max_properties)) {
   5474           return false;
   5475         }
   5476       }
   5477     }
   5478   }
   5479   return true;
   5480 }
   5481 
   5482 
   5483 void HOptimizedGraphBuilder::VisitObjectLiteral(ObjectLiteral* expr) {
   5484   DCHECK(!HasStackOverflow());
   5485   DCHECK(current_block() != NULL);
   5486   DCHECK(current_block()->HasPredecessor());
   5487 
   5488   Handle<JSFunction> closure = function_state()->compilation_info()->closure();
   5489   HInstruction* literal;
   5490 
   5491   // Check whether to use fast or slow deep-copying for boilerplate.
   5492   int max_properties = kMaxFastLiteralProperties;
   5493   Handle<Object> literals_cell(
   5494       closure->literals()->literal(expr->literal_index()), isolate());
   5495   Handle<AllocationSite> site;
   5496   Handle<JSObject> boilerplate;
   5497   if (!literals_cell->IsUndefined(isolate())) {
   5498     // Retrieve the boilerplate
   5499     site = Handle<AllocationSite>::cast(literals_cell);
   5500     boilerplate = Handle<JSObject>(JSObject::cast(site->transition_info()),
   5501                                    isolate());
   5502   }
   5503 
   5504   if (!boilerplate.is_null() &&
   5505       IsFastLiteral(boilerplate, kMaxFastLiteralDepth, &max_properties)) {
   5506     AllocationSiteUsageContext site_context(isolate(), site, false);
   5507     site_context.EnterNewScope();
   5508     literal = BuildFastLiteral(boilerplate, &site_context);
   5509     site_context.ExitScope(site, boilerplate);
   5510   } else {
   5511     NoObservableSideEffectsScope no_effects(this);
   5512     Handle<FixedArray> constant_properties = expr->constant_properties();
   5513     int literal_index = expr->literal_index();
   5514     int flags = expr->ComputeFlags(true);
   5515 
   5516     Add<HPushArguments>(AddThisFunction(), Add<HConstant>(literal_index),
   5517                         Add<HConstant>(constant_properties),
   5518                         Add<HConstant>(flags));
   5519 
   5520     Runtime::FunctionId function_id = Runtime::kCreateObjectLiteral;
   5521     literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
   5522   }
   5523 
   5524   // The object is expected in the bailout environment during computation
   5525   // of the property values and is the value of the entire expression.
   5526   Push(literal);
   5527   for (int i = 0; i < expr->properties()->length(); i++) {
   5528     ObjectLiteral::Property* property = expr->properties()->at(i);
   5529     if (property->is_computed_name()) return Bailout(kComputedPropertyName);
   5530     if (property->IsCompileTimeValue()) continue;
   5531 
   5532     Literal* key = property->key()->AsLiteral();
   5533     Expression* value = property->value();
   5534 
   5535     switch (property->kind()) {
   5536       case ObjectLiteral::Property::MATERIALIZED_LITERAL:
   5537         DCHECK(!CompileTimeValue::IsCompileTimeValue(value));
   5538         // Fall through.
   5539       case ObjectLiteral::Property::COMPUTED:
   5540         // It is safe to use [[Put]] here because the boilerplate already
   5541         // contains computed properties with an uninitialized value.
   5542         if (key->IsStringLiteral()) {
   5543           DCHECK(key->IsPropertyName());
   5544           if (property->emit_store()) {
   5545             CHECK_ALIVE(VisitForValue(value));
   5546             HValue* value = Pop();
   5547 
   5548             Handle<Map> map = property->GetReceiverType();
   5549             Handle<String> name = key->AsPropertyName();
   5550             HValue* store;
   5551             FeedbackVectorSlot slot = property->GetSlot();
   5552             if (map.is_null()) {
   5553               // If we don't know the monomorphic type, do a generic store.
   5554               CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot, literal,
   5555                                                     name, value));
   5556             } else {
   5557               PropertyAccessInfo info(this, STORE, map, name);
   5558               if (info.CanAccessMonomorphic()) {
   5559                 HValue* checked_literal = Add<HCheckMaps>(literal, map);
   5560                 DCHECK(!info.IsAccessorConstant());
   5561                 store = BuildMonomorphicAccess(
   5562                     &info, literal, checked_literal, value,
   5563                     BailoutId::None(), BailoutId::None());
   5564               } else {
   5565                 CHECK_ALIVE(store = BuildNamedGeneric(STORE, NULL, slot,
   5566                                                       literal, name, value));
   5567               }
   5568             }
   5569             if (store->IsInstruction()) {
   5570               AddInstruction(HInstruction::cast(store));
   5571             }
   5572             DCHECK(store->HasObservableSideEffects());
   5573             Add<HSimulate>(key->id(), REMOVABLE_SIMULATE);
   5574 
   5575             // Add [[HomeObject]] to function literals.
   5576             if (FunctionLiteral::NeedsHomeObject(property->value())) {
   5577               Handle<Symbol> sym = isolate()->factory()->home_object_symbol();
   5578               HInstruction* store_home = BuildNamedGeneric(
   5579                   STORE, NULL, property->GetSlot(1), value, sym, literal);
   5580               AddInstruction(store_home);
   5581               DCHECK(store_home->HasObservableSideEffects());
   5582               Add<HSimulate>(property->value()->id(), REMOVABLE_SIMULATE);
   5583             }
   5584           } else {
   5585             CHECK_ALIVE(VisitForEffect(value));
   5586           }
   5587           break;
   5588         }
   5589         // Fall through.
   5590       case ObjectLiteral::Property::PROTOTYPE:
   5591       case ObjectLiteral::Property::SETTER:
   5592       case ObjectLiteral::Property::GETTER:
   5593         return Bailout(kObjectLiteralWithComplexProperty);
   5594       default: UNREACHABLE();
   5595     }
   5596   }
   5597 
   5598   return ast_context()->ReturnValue(Pop());
   5599 }
   5600 
   5601 
   5602 void HOptimizedGraphBuilder::VisitArrayLiteral(ArrayLiteral* expr) {
   5603   DCHECK(!HasStackOverflow());
   5604   DCHECK(current_block() != NULL);
   5605   DCHECK(current_block()->HasPredecessor());
   5606   ZoneList<Expression*>* subexprs = expr->values();
   5607   int length = subexprs->length();
   5608   HInstruction* literal;
   5609 
   5610   Handle<AllocationSite> site;
   5611   Handle<LiteralsArray> literals(environment()->closure()->literals(),
   5612                                  isolate());
   5613   Handle<Object> literals_cell(literals->literal(expr->literal_index()),
   5614                                isolate());
   5615   Handle<JSObject> boilerplate_object;
   5616   if (!literals_cell->IsUndefined(isolate())) {
   5617     DCHECK(literals_cell->IsAllocationSite());
   5618     site = Handle<AllocationSite>::cast(literals_cell);
   5619     boilerplate_object = Handle<JSObject>(
   5620         JSObject::cast(site->transition_info()), isolate());
   5621   }
   5622 
   5623   // Check whether to use fast or slow deep-copying for boilerplate.
   5624   int max_properties = kMaxFastLiteralProperties;
   5625   if (!boilerplate_object.is_null() &&
   5626       IsFastLiteral(boilerplate_object, kMaxFastLiteralDepth,
   5627                     &max_properties)) {
   5628     DCHECK(site->SitePointsToLiteral());
   5629     AllocationSiteUsageContext site_context(isolate(), site, false);
   5630     site_context.EnterNewScope();
   5631     literal = BuildFastLiteral(boilerplate_object, &site_context);
   5632     site_context.ExitScope(site, boilerplate_object);
   5633   } else {
   5634     NoObservableSideEffectsScope no_effects(this);
   5635     Handle<FixedArray> constants = expr->constant_elements();
   5636     int literal_index = expr->literal_index();
   5637     int flags = expr->ComputeFlags(true);
   5638 
   5639     Add<HPushArguments>(AddThisFunction(), Add<HConstant>(literal_index),
   5640                         Add<HConstant>(constants), Add<HConstant>(flags));
   5641 
   5642     Runtime::FunctionId function_id = Runtime::kCreateArrayLiteral;
   5643     literal = Add<HCallRuntime>(Runtime::FunctionForId(function_id), 4);
   5644 
   5645     // Register to deopt if the boilerplate ElementsKind changes.
   5646     if (!site.is_null()) {
   5647       top_info()->dependencies()->AssumeTransitionStable(site);
   5648     }
   5649   }
   5650 
   5651   // The array is expected in the bailout environment during computation
   5652   // of the property values and is the value of the entire expression.
   5653   Push(literal);
   5654 
   5655   HInstruction* elements = NULL;
   5656 
   5657   for (int i = 0; i < length; i++) {
   5658     Expression* subexpr = subexprs->at(i);
   5659     DCHECK(!subexpr->IsSpread());
   5660 
   5661     // If the subexpression is a literal or a simple materialized literal it
   5662     // is already set in the cloned array.
   5663     if (CompileTimeValue::IsCompileTimeValue(subexpr)) continue;
   5664 
   5665     CHECK_ALIVE(VisitForValue(subexpr));
   5666     HValue* value = Pop();
   5667     if (!Smi::IsValid(i)) return Bailout(kNonSmiKeyInArrayLiteral);
   5668 
   5669     elements = AddLoadElements(literal);
   5670 
   5671     HValue* key = Add<HConstant>(i);
   5672 
   5673     if (!boilerplate_object.is_null()) {
   5674       ElementsKind boilerplate_elements_kind =
   5675           boilerplate_object->GetElementsKind();
   5676       switch (boilerplate_elements_kind) {
   5677         case FAST_SMI_ELEMENTS:
   5678         case FAST_HOLEY_SMI_ELEMENTS:
   5679         case FAST_ELEMENTS:
   5680         case FAST_HOLEY_ELEMENTS:
   5681         case FAST_DOUBLE_ELEMENTS:
   5682         case FAST_HOLEY_DOUBLE_ELEMENTS: {
   5683           Add<HStoreKeyed>(elements, key, value, nullptr,
   5684                            boilerplate_elements_kind);
   5685           break;
   5686         }
   5687         default:
   5688           UNREACHABLE();
   5689           break;
   5690       }
   5691     } else {
   5692       HInstruction* instr = BuildKeyedGeneric(
   5693           STORE, expr, expr->LiteralFeedbackSlot(), literal, key, value);
   5694       AddInstruction(instr);
   5695     }
   5696 
   5697     Add<HSimulate>(expr->GetIdForElement(i));
   5698   }
   5699 
   5700   return ast_context()->ReturnValue(Pop());
   5701 }
   5702 
   5703 
   5704 HCheckMaps* HOptimizedGraphBuilder::AddCheckMap(HValue* object,
   5705                                                 Handle<Map> map) {
   5706   BuildCheckHeapObject(object);
   5707   return Add<HCheckMaps>(object, map);
   5708 }
   5709 
   5710 
   5711 HInstruction* HOptimizedGraphBuilder::BuildLoadNamedField(
   5712     PropertyAccessInfo* info,
   5713     HValue* checked_object) {
   5714   // See if this is a load for an immutable property
   5715   if (checked_object->ActualValue()->IsConstant()) {
   5716     Handle<Object> object(
   5717         HConstant::cast(checked_object->ActualValue())->handle(isolate()));
   5718 
   5719     if (object->IsJSObject()) {
   5720       LookupIterator it(object, info->name(),
   5721                         LookupIterator::OWN_SKIP_INTERCEPTOR);
   5722       Handle<Object> value = JSReceiver::GetDataProperty(&it);
   5723       if (it.IsFound() && it.IsReadOnly() && !it.IsConfigurable()) {
   5724         return New<HConstant>(value);
   5725       }
   5726     }
   5727   }
   5728 
   5729   HObjectAccess access = info->access();
   5730   if (access.representation().IsDouble() &&
   5731       (!FLAG_unbox_double_fields || !access.IsInobject())) {
   5732     // Load the heap number.
   5733     checked_object = Add<HLoadNamedField>(
   5734         checked_object, nullptr,
   5735         access.WithRepresentation(Representation::Tagged()));
   5736     // Load the double value from it.
   5737     access = HObjectAccess::ForHeapNumberValue();
   5738   }
   5739 
   5740   SmallMapList* map_list = info->field_maps();
   5741   if (map_list->length() == 0) {
   5742     return New<HLoadNamedField>(checked_object, checked_object, access);
   5743   }
   5744 
   5745   UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(map_list->length(), zone());
   5746   for (int i = 0; i < map_list->length(); ++i) {
   5747     maps->Add(Unique<Map>::CreateImmovable(map_list->at(i)), zone());
   5748   }
   5749   return New<HLoadNamedField>(
   5750       checked_object, checked_object, access, maps, info->field_type());
   5751 }
   5752 
   5753 
   5754 HInstruction* HOptimizedGraphBuilder::BuildStoreNamedField(
   5755     PropertyAccessInfo* info,
   5756     HValue* checked_object,
   5757     HValue* value) {
   5758   bool transition_to_field = info->IsTransition();
   5759   // TODO(verwaest): Move this logic into PropertyAccessInfo.
   5760   HObjectAccess field_access = info->access();
   5761 
   5762   HStoreNamedField *instr;
   5763   if (field_access.representation().IsDouble() &&
   5764       (!FLAG_unbox_double_fields || !field_access.IsInobject())) {
   5765     HObjectAccess heap_number_access =
   5766         field_access.WithRepresentation(Representation::Tagged());
   5767     if (transition_to_field) {
   5768       // The store requires a mutable HeapNumber to be allocated.
   5769       NoObservableSideEffectsScope no_side_effects(this);
   5770       HInstruction* heap_number_size = Add<HConstant>(HeapNumber::kSize);
   5771 
   5772       // TODO(hpayer): Allocation site pretenuring support.
   5773       HInstruction* heap_number =
   5774           Add<HAllocate>(heap_number_size, HType::HeapObject(), NOT_TENURED,
   5775                          MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0());
   5776       AddStoreMapConstant(
   5777           heap_number, isolate()->factory()->mutable_heap_number_map());
   5778       Add<HStoreNamedField>(heap_number, HObjectAccess::ForHeapNumberValue(),
   5779                             value);
   5780       instr = New<HStoreNamedField>(checked_object->ActualValue(),
   5781                                     heap_number_access,
   5782                                     heap_number);
   5783     } else {
   5784       // Already holds a HeapNumber; load the box and write its value field.
   5785       HInstruction* heap_number =
   5786           Add<HLoadNamedField>(checked_object, nullptr, heap_number_access);
   5787       instr = New<HStoreNamedField>(heap_number,
   5788                                     HObjectAccess::ForHeapNumberValue(),
   5789                                     value, STORE_TO_INITIALIZED_ENTRY);
   5790     }
   5791   } else {
   5792     if (field_access.representation().IsHeapObject()) {
   5793       BuildCheckHeapObject(value);
   5794     }
   5795 
   5796     if (!info->field_maps()->is_empty()) {
   5797       DCHECK(field_access.representation().IsHeapObject());
   5798       value = Add<HCheckMaps>(value, info->field_maps());
   5799     }
   5800 
   5801     // This is a normal store.
   5802     instr = New<HStoreNamedField>(
   5803         checked_object->ActualValue(), field_access, value,
   5804         transition_to_field ? INITIALIZING_STORE : STORE_TO_INITIALIZED_ENTRY);
   5805   }
   5806 
   5807   if (transition_to_field) {
   5808     Handle<Map> transition(info->transition());
   5809     DCHECK(!transition->is_deprecated());
   5810     instr->SetTransition(Add<HConstant>(transition));
   5811   }
   5812   return instr;
   5813 }
   5814 
   5815 Handle<FieldType>
   5816 HOptimizedGraphBuilder::PropertyAccessInfo::GetFieldTypeFromMap(
   5817     Handle<Map> map) const {
   5818   DCHECK(IsFound());
   5819   DCHECK(number_ < map->NumberOfOwnDescriptors());
   5820   return handle(map->instance_descriptors()->GetFieldType(number_), isolate());
   5821 }
   5822 
   5823 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsCompatible(
   5824     PropertyAccessInfo* info) {
   5825   if (!CanInlinePropertyAccess(map_)) return false;
   5826 
   5827   // Currently only handle AstType::Number as a polymorphic case.
   5828   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
   5829   // instruction.
   5830   if (IsNumberType()) return false;
   5831 
   5832   // Values are only compatible for monomorphic load if they all behave the same
   5833   // regarding value wrappers.
   5834   if (IsValueWrapped() != info->IsValueWrapped()) return false;
   5835 
   5836   if (!LookupDescriptor()) return false;
   5837 
   5838   if (!IsFound()) {
   5839     return (!info->IsFound() || info->has_holder()) &&
   5840            map()->prototype() == info->map()->prototype();
   5841   }
   5842 
   5843   // Mismatch if the other access info found the property in the prototype
   5844   // chain.
   5845   if (info->has_holder()) return false;
   5846 
   5847   if (IsAccessorConstant()) {
   5848     return accessor_.is_identical_to(info->accessor_) &&
   5849         api_holder_.is_identical_to(info->api_holder_);
   5850   }
   5851 
   5852   if (IsDataConstant()) {
   5853     return constant_.is_identical_to(info->constant_);
   5854   }
   5855 
   5856   DCHECK(IsData());
   5857   if (!info->IsData()) return false;
   5858 
   5859   Representation r = access_.representation();
   5860   if (IsLoad()) {
   5861     if (!info->access_.representation().IsCompatibleForLoad(r)) return false;
   5862   } else {
   5863     if (!info->access_.representation().IsCompatibleForStore(r)) return false;
   5864   }
   5865   if (info->access_.offset() != access_.offset()) return false;
   5866   if (info->access_.IsInobject() != access_.IsInobject()) return false;
   5867   if (IsLoad()) {
   5868     if (field_maps_.is_empty()) {
   5869       info->field_maps_.Clear();
   5870     } else if (!info->field_maps_.is_empty()) {
   5871       for (int i = 0; i < field_maps_.length(); ++i) {
   5872         info->field_maps_.AddMapIfMissing(field_maps_.at(i), info->zone());
   5873       }
   5874       info->field_maps_.Sort();
   5875     }
   5876   } else {
   5877     // We can only merge stores that agree on their field maps. The comparison
   5878     // below is safe, since we keep the field maps sorted.
   5879     if (field_maps_.length() != info->field_maps_.length()) return false;
   5880     for (int i = 0; i < field_maps_.length(); ++i) {
   5881       if (!field_maps_.at(i).is_identical_to(info->field_maps_.at(i))) {
   5882         return false;
   5883       }
   5884     }
   5885   }
   5886   info->GeneralizeRepresentation(r);
   5887   info->field_type_ = info->field_type_.Combine(field_type_);
   5888   return true;
   5889 }
   5890 
   5891 
   5892 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupDescriptor() {
   5893   if (!map_->IsJSObjectMap()) return true;
   5894   LookupDescriptor(*map_, *name_);
   5895   return LoadResult(map_);
   5896 }
   5897 
   5898 
   5899 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadResult(Handle<Map> map) {
   5900   if (!IsLoad() && IsProperty() && IsReadOnly()) {
   5901     return false;
   5902   }
   5903 
   5904   if (IsData()) {
   5905     // Construct the object field access.
   5906     int index = GetLocalFieldIndexFromMap(map);
   5907     access_ = HObjectAccess::ForField(map, index, representation(), name_);
   5908 
   5909     // Load field map for heap objects.
   5910     return LoadFieldMaps(map);
   5911   } else if (IsAccessorConstant()) {
   5912     Handle<Object> accessors = GetAccessorsFromMap(map);
   5913     if (!accessors->IsAccessorPair()) return false;
   5914     Object* raw_accessor =
   5915         IsLoad() ? Handle<AccessorPair>::cast(accessors)->getter()
   5916                  : Handle<AccessorPair>::cast(accessors)->setter();
   5917     if (!raw_accessor->IsJSFunction() &&
   5918         !raw_accessor->IsFunctionTemplateInfo())
   5919       return false;
   5920     Handle<Object> accessor = handle(HeapObject::cast(raw_accessor));
   5921     CallOptimization call_optimization(accessor);
   5922     if (call_optimization.is_simple_api_call()) {
   5923       CallOptimization::HolderLookup holder_lookup;
   5924       api_holder_ =
   5925           call_optimization.LookupHolderOfExpectedType(map_, &holder_lookup);
   5926     }
   5927     accessor_ = accessor;
   5928   } else if (IsDataConstant()) {
   5929     constant_ = GetConstantFromMap(map);
   5930   }
   5931 
   5932   return true;
   5933 }
   5934 
   5935 
   5936 bool HOptimizedGraphBuilder::PropertyAccessInfo::LoadFieldMaps(
   5937     Handle<Map> map) {
   5938   // Clear any previously collected field maps/type.
   5939   field_maps_.Clear();
   5940   field_type_ = HType::Tagged();
   5941 
   5942   // Figure out the field type from the accessor map.
   5943   Handle<FieldType> field_type = GetFieldTypeFromMap(map);
   5944 
   5945   // Collect the (stable) maps from the field type.
   5946   if (field_type->IsClass()) {
   5947     DCHECK(access_.representation().IsHeapObject());
   5948     Handle<Map> field_map = field_type->AsClass();
   5949     if (field_map->is_stable()) {
   5950       field_maps_.Add(field_map, zone());
   5951     }
   5952   }
   5953 
   5954   if (field_maps_.is_empty()) {
   5955     // Store is not safe if the field map was cleared.
   5956     return IsLoad() || !field_type->IsNone();
   5957   }
   5958 
   5959   // Determine field HType from field type.
   5960   field_type_ = HType::FromFieldType(field_type, zone());
   5961   DCHECK(field_type_.IsHeapObject());
   5962 
   5963   // Add dependency on the map that introduced the field.
   5964   top_info()->dependencies()->AssumeFieldOwner(GetFieldOwnerFromMap(map));
   5965   return true;
   5966 }
   5967 
   5968 
   5969 bool HOptimizedGraphBuilder::PropertyAccessInfo::LookupInPrototypes() {
   5970   Handle<Map> map = this->map();
   5971   if (name_->IsPrivate()) {
   5972     NotFound();
   5973     return !map->has_hidden_prototype();
   5974   }
   5975 
   5976   while (map->prototype()->IsJSObject()) {
   5977     holder_ = handle(JSObject::cast(map->prototype()));
   5978     if (holder_->map()->is_deprecated()) {
   5979       JSObject::TryMigrateInstance(holder_);
   5980     }
   5981     map = Handle<Map>(holder_->map());
   5982     if (!CanInlinePropertyAccess(map)) {
   5983       NotFound();
   5984       return false;
   5985     }
   5986     LookupDescriptor(*map, *name_);
   5987     if (IsFound()) return LoadResult(map);
   5988   }
   5989 
   5990   NotFound();
   5991   return !map->prototype()->IsJSReceiver();
   5992 }
   5993 
   5994 
   5995 bool HOptimizedGraphBuilder::PropertyAccessInfo::IsIntegerIndexedExotic() {
   5996   InstanceType instance_type = map_->instance_type();
   5997   return instance_type == JS_TYPED_ARRAY_TYPE && name_->IsString() &&
   5998          IsSpecialIndex(isolate()->unicode_cache(), String::cast(*name_));
   5999 }
   6000 
   6001 
   6002 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessMonomorphic() {
   6003   if (!CanInlinePropertyAccess(map_)) return false;
   6004   if (IsJSObjectFieldAccessor()) return IsLoad();
   6005   if (map_->IsJSFunctionMap() && map_->is_constructor() &&
   6006       !map_->has_non_instance_prototype() &&
   6007       name_.is_identical_to(isolate()->factory()->prototype_string())) {
   6008     return IsLoad();
   6009   }
   6010   if (!LookupDescriptor()) return false;
   6011   if (IsFound()) return IsLoad() || !IsReadOnly();
   6012   if (IsIntegerIndexedExotic()) return false;
   6013   if (!LookupInPrototypes()) return false;
   6014   if (IsLoad()) return true;
   6015 
   6016   if (IsAccessorConstant()) return true;
   6017   LookupTransition(*map_, *name_, NONE);
   6018   if (IsTransitionToData() && map_->unused_property_fields() > 0) {
   6019     // Construct the object field access.
   6020     int descriptor = transition()->LastAdded();
   6021     int index =
   6022         transition()->instance_descriptors()->GetFieldIndex(descriptor) -
   6023         map_->GetInObjectProperties();
   6024     PropertyDetails details =
   6025         transition()->instance_descriptors()->GetDetails(descriptor);
   6026     Representation representation = details.representation();
   6027     access_ = HObjectAccess::ForField(map_, index, representation, name_);
   6028 
   6029     // Load field map for heap objects.
   6030     return LoadFieldMaps(transition());
   6031   }
   6032   return false;
   6033 }
   6034 
   6035 
   6036 bool HOptimizedGraphBuilder::PropertyAccessInfo::CanAccessAsMonomorphic(
   6037     SmallMapList* maps) {
   6038   DCHECK(map_.is_identical_to(maps->first()));
   6039   if (!CanAccessMonomorphic()) return false;
   6040   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
   6041   if (maps->length() > kMaxLoadPolymorphism) return false;
   6042   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
   6043   if (GetJSObjectFieldAccess(&access)) {
   6044     for (int i = 1; i < maps->length(); ++i) {
   6045       PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
   6046       HObjectAccess test_access = HObjectAccess::ForMap();  // bogus default
   6047       if (!test_info.GetJSObjectFieldAccess(&test_access)) return false;
   6048       if (!access.Equals(test_access)) return false;
   6049     }
   6050     return true;
   6051   }
   6052 
   6053   // Currently only handle numbers as a polymorphic case.
   6054   // TODO(verwaest): Support monomorphic handling of numbers with a HCheckNumber
   6055   // instruction.
   6056   if (IsNumberType()) return false;
   6057 
   6058   // Multiple maps cannot transition to the same target map.
   6059   DCHECK(!IsLoad() || !IsTransition());
   6060   if (IsTransition() && maps->length() > 1) return false;
   6061 
   6062   for (int i = 1; i < maps->length(); ++i) {
   6063     PropertyAccessInfo test_info(builder_, access_type_, maps->at(i), name_);
   6064     if (!test_info.IsCompatible(this)) return false;
   6065   }
   6066 
   6067   return true;
   6068 }
   6069 
   6070 
   6071 Handle<Map> HOptimizedGraphBuilder::PropertyAccessInfo::map() {
   6072   Handle<JSFunction> ctor;
   6073   if (Map::GetConstructorFunction(
   6074           map_, handle(current_info()->closure()->context()->native_context()))
   6075           .ToHandle(&ctor)) {
   6076     return handle(ctor->initial_map());
   6077   }
   6078   return map_;
   6079 }
   6080 
   6081 
   6082 static bool NeedsWrapping(Handle<Map> map, Handle<JSFunction> target) {
   6083   return !map->IsJSObjectMap() &&
   6084          is_sloppy(target->shared()->language_mode()) &&
   6085          !target->shared()->native();
   6086 }
   6087 
   6088 
   6089 bool HOptimizedGraphBuilder::PropertyAccessInfo::NeedsWrappingFor(
   6090     Handle<JSFunction> target) const {
   6091   return NeedsWrapping(map_, target);
   6092 }
   6093 
   6094 
   6095 HValue* HOptimizedGraphBuilder::BuildMonomorphicAccess(
   6096     PropertyAccessInfo* info, HValue* object, HValue* checked_object,
   6097     HValue* value, BailoutId ast_id, BailoutId return_id,
   6098     bool can_inline_accessor) {
   6099   HObjectAccess access = HObjectAccess::ForMap();  // bogus default
   6100   if (info->GetJSObjectFieldAccess(&access)) {
   6101     DCHECK(info->IsLoad());
   6102     return New<HLoadNamedField>(object, checked_object, access);
   6103   }
   6104 
   6105   if (info->name().is_identical_to(isolate()->factory()->prototype_string()) &&
   6106       info->map()->IsJSFunctionMap() && info->map()->is_constructor()) {
   6107     DCHECK(!info->map()->has_non_instance_prototype());
   6108     return New<HLoadFunctionPrototype>(checked_object);
   6109   }
   6110 
   6111   HValue* checked_holder = checked_object;
   6112   if (info->has_holder()) {
   6113     Handle<JSObject> prototype(JSObject::cast(info->map()->prototype()));
   6114     checked_holder = BuildCheckPrototypeMaps(prototype, info->holder());
   6115   }
   6116 
   6117   if (!info->IsFound()) {
   6118     DCHECK(info->IsLoad());
   6119     return graph()->GetConstantUndefined();
   6120   }
   6121 
   6122   if (info->IsData()) {
   6123     if (info->IsLoad()) {
   6124       return BuildLoadNamedField(info, checked_holder);
   6125     } else {
   6126       return BuildStoreNamedField(info, checked_object, value);
   6127     }
   6128   }
   6129 
   6130   if (info->IsTransition()) {
   6131     DCHECK(!info->IsLoad());
   6132     return BuildStoreNamedField(info, checked_object, value);
   6133   }
   6134 
   6135   if (info->IsAccessorConstant()) {
   6136     MaybeHandle<Name> maybe_name =
   6137         FunctionTemplateInfo::TryGetCachedPropertyName(isolate(),
   6138                                                        info->accessor());
   6139     if (!maybe_name.is_null()) {
   6140       Handle<Name> name = maybe_name.ToHandleChecked();
   6141       PropertyAccessInfo cache_info(this, LOAD, info->map(), name);
   6142       // Load new target.
   6143       if (cache_info.CanAccessMonomorphic()) {
   6144         return BuildLoadNamedField(&cache_info, checked_object);
   6145       }
   6146     }
   6147 
   6148     Push(checked_object);
   6149     int argument_count = 1;
   6150     if (!info->IsLoad()) {
   6151       argument_count = 2;
   6152       Push(value);
   6153     }
   6154 
   6155     if (info->accessor()->IsJSFunction() &&
   6156         info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) {
   6157       HValue* function = Add<HConstant>(info->accessor());
   6158       PushArgumentsFromEnvironment(argument_count);
   6159       return NewCallFunction(function, argument_count, TailCallMode::kDisallow,
   6160                              ConvertReceiverMode::kNotNullOrUndefined,
   6161                              TailCallMode::kDisallow);
   6162     } else if (FLAG_inline_accessors && can_inline_accessor) {
   6163       bool success = info->IsLoad()
   6164           ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id)
   6165           : TryInlineSetter(
   6166               info->accessor(), info->map(), ast_id, return_id, value);
   6167       if (success || HasStackOverflow()) return NULL;
   6168     }
   6169 
   6170     PushArgumentsFromEnvironment(argument_count);
   6171     if (!info->accessor()->IsJSFunction()) {
   6172       Bailout(kInliningBailedOut);
   6173       return nullptr;
   6174     }
   6175     return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()),
   6176                                    argument_count, TailCallMode::kDisallow,
   6177                                    TailCallMode::kDisallow);
   6178   }
   6179 
   6180   DCHECK(info->IsDataConstant());
   6181   if (info->IsLoad()) {
   6182     return New<HConstant>(info->constant());
   6183   } else {
   6184     return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant()));
   6185   }
   6186 }
   6187 
   6188 
   6189 void HOptimizedGraphBuilder::HandlePolymorphicNamedFieldAccess(
   6190     PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
   6191     BailoutId ast_id, BailoutId return_id, HValue* object, HValue* value,
   6192     SmallMapList* maps, Handle<Name> name) {
   6193   // Something did not match; must use a polymorphic load.
   6194   int count = 0;
   6195   HBasicBlock* join = NULL;
   6196   HBasicBlock* number_block = NULL;
   6197   bool handled_string = false;
   6198 
   6199   bool handle_smi = false;
   6200   STATIC_ASSERT(kMaxLoadPolymorphism == kMaxStorePolymorphism);
   6201   int i;
   6202   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
   6203     PropertyAccessInfo info(this, access_type, maps->at(i), name);
   6204     if (info.IsStringType()) {
   6205       if (handled_string) continue;
   6206       handled_string = true;
   6207     }
   6208     if (info.CanAccessMonomorphic()) {
   6209       count++;
   6210       if (info.IsNumberType()) {
   6211         handle_smi = true;
   6212         break;
   6213       }
   6214     }
   6215   }
   6216 
   6217   if (i < maps->length()) {
   6218     count = -1;
   6219     maps->Clear();
   6220   } else {
   6221     count = 0;
   6222   }
   6223   HControlInstruction* smi_check = NULL;
   6224   handled_string = false;
   6225 
   6226   for (i = 0; i < maps->length() && count < kMaxLoadPolymorphism; ++i) {
   6227     PropertyAccessInfo info(this, access_type, maps->at(i), name);
   6228     if (info.IsStringType()) {
   6229       if (handled_string) continue;
   6230       handled_string = true;
   6231     }
   6232     if (!info.CanAccessMonomorphic()) continue;
   6233 
   6234     if (count == 0) {
   6235       join = graph()->CreateBasicBlock();
   6236       if (handle_smi) {
   6237         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
   6238         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
   6239         number_block = graph()->CreateBasicBlock();
   6240         smi_check = New<HIsSmiAndBranch>(
   6241             object, empty_smi_block, not_smi_block);
   6242         FinishCurrentBlock(smi_check);
   6243         GotoNoSimulate(empty_smi_block, number_block);
   6244         set_current_block(not_smi_block);
   6245       } else {
   6246         BuildCheckHeapObject(object);
   6247       }
   6248     }
   6249     ++count;
   6250     HBasicBlock* if_true = graph()->CreateBasicBlock();
   6251     HBasicBlock* if_false = graph()->CreateBasicBlock();
   6252     HUnaryControlInstruction* compare;
   6253 
   6254     HValue* dependency;
   6255     if (info.IsNumberType()) {
   6256       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
   6257       compare = New<HCompareMap>(object, heap_number_map, if_true, if_false);
   6258       dependency = smi_check;
   6259     } else if (info.IsStringType()) {
   6260       compare = New<HIsStringAndBranch>(object, if_true, if_false);
   6261       dependency = compare;
   6262     } else {
   6263       compare = New<HCompareMap>(object, info.map(), if_true, if_false);
   6264       dependency = compare;
   6265     }
   6266     FinishCurrentBlock(compare);
   6267 
   6268     if (info.IsNumberType()) {
   6269       GotoNoSimulate(if_true, number_block);
   6270       if_true = number_block;
   6271     }
   6272 
   6273     set_current_block(if_true);
   6274 
   6275     HValue* access =
   6276         BuildMonomorphicAccess(&info, object, dependency, value, ast_id,
   6277                                return_id, FLAG_polymorphic_inlining);
   6278 
   6279     HValue* result = NULL;
   6280     switch (access_type) {
   6281       case LOAD:
   6282         result = access;
   6283         break;
   6284       case STORE:
   6285         result = value;
   6286         break;
   6287     }
   6288 
   6289     if (access == NULL) {
   6290       if (HasStackOverflow()) return;
   6291     } else {
   6292       if (access->IsInstruction()) {
   6293         HInstruction* instr = HInstruction::cast(access);
   6294         if (!instr->IsLinked()) AddInstruction(instr);
   6295       }
   6296       if (!ast_context()->IsEffect()) Push(result);
   6297     }
   6298 
   6299     if (current_block() != NULL) Goto(join);
   6300     set_current_block(if_false);
   6301   }
   6302 
   6303   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
   6304   // know about and do not want to handle ones we've never seen.  Otherwise
   6305   // use a generic IC.
   6306   if (count == maps->length() && FLAG_deoptimize_uncommon_cases) {
   6307     FinishExitWithHardDeoptimization(
   6308         DeoptimizeReason::kUnknownMapInPolymorphicAccess);
   6309   } else {
   6310     HInstruction* instr =
   6311         BuildNamedGeneric(access_type, expr, slot, object, name, value);
   6312     AddInstruction(instr);
   6313     if (!ast_context()->IsEffect()) Push(access_type == LOAD ? instr : value);
   6314 
   6315     if (join != NULL) {
   6316       Goto(join);
   6317     } else {
   6318       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6319       if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
   6320       return;
   6321     }
   6322   }
   6323 
   6324   DCHECK(join != NULL);
   6325   if (join->HasPredecessor()) {
   6326     join->SetJoinId(ast_id);
   6327     set_current_block(join);
   6328     if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop());
   6329   } else {
   6330     set_current_block(NULL);
   6331   }
   6332 }
   6333 
   6334 static bool ComputeReceiverTypes(Expression* expr, HValue* receiver,
   6335                                  SmallMapList** t,
   6336                                  HOptimizedGraphBuilder* builder) {
   6337   Zone* zone = builder->zone();
   6338   SmallMapList* maps = expr->GetReceiverTypes();
   6339   *t = maps;
   6340   bool monomorphic = expr->IsMonomorphic();
   6341   if (maps != nullptr && receiver->HasMonomorphicJSObjectType()) {
   6342     if (maps->length() > 0) {
   6343       Map* root_map = receiver->GetMonomorphicJSObjectMap()->FindRootMap();
   6344       maps->FilterForPossibleTransitions(root_map);
   6345       monomorphic = maps->length() == 1;
   6346     } else {
   6347       // No type feedback, see if we can infer the type. This is safely
   6348       // possible if the receiver had a known map at some point, and no
   6349       // map-changing stores have happened to it since.
   6350       Handle<Map> candidate_map = receiver->GetMonomorphicJSObjectMap();
   6351       for (HInstruction* current = builder->current_block()->last();
   6352            current != nullptr; current = current->previous()) {
   6353         if (current->IsBlockEntry()) break;
   6354         if (current->CheckChangesFlag(kMaps)) {
   6355           // Only allow map changes that store the candidate map. We don't
   6356           // need to care which object the map is being written into.
   6357           if (!current->IsStoreNamedField()) break;
   6358           HStoreNamedField* map_change = HStoreNamedField::cast(current);
   6359           if (!map_change->value()->IsConstant()) break;
   6360           HConstant* map_constant = HConstant::cast(map_change->value());
   6361           if (!map_constant->representation().IsTagged()) break;
   6362           Handle<Object> map = map_constant->handle(builder->isolate());
   6363           if (!map.is_identical_to(candidate_map)) break;
   6364         }
   6365         if (current == receiver) {
   6366           // We made it all the way back to the receiver without encountering
   6367           // a map change! So we can assume that the receiver still has the
   6368           // candidate_map we know about.
   6369           maps->Add(candidate_map, zone);
   6370           monomorphic = true;
   6371           break;
   6372         }
   6373       }
   6374     }
   6375   }
   6376   return monomorphic && CanInlinePropertyAccess(maps->first());
   6377 }
   6378 
   6379 
   6380 static bool AreStringTypes(SmallMapList* maps) {
   6381   for (int i = 0; i < maps->length(); i++) {
   6382     if (maps->at(i)->instance_type() >= FIRST_NONSTRING_TYPE) return false;
   6383   }
   6384   return true;
   6385 }
   6386 
   6387 void HOptimizedGraphBuilder::BuildStore(Expression* expr, Property* prop,
   6388                                         FeedbackVectorSlot slot,
   6389                                         BailoutId ast_id, BailoutId return_id,
   6390                                         bool is_uninitialized) {
   6391   if (!prop->key()->IsPropertyName()) {
   6392     // Keyed store.
   6393     HValue* value = Pop();
   6394     HValue* key = Pop();
   6395     HValue* object = Pop();
   6396     bool has_side_effects = false;
   6397     HValue* result =
   6398         HandleKeyedElementAccess(object, key, value, expr, slot, ast_id,
   6399                                  return_id, STORE, &has_side_effects);
   6400     if (has_side_effects) {
   6401       if (!ast_context()->IsEffect()) Push(value);
   6402       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6403       if (!ast_context()->IsEffect()) Drop(1);
   6404     }
   6405     if (result == NULL) return;
   6406     return ast_context()->ReturnValue(value);
   6407   }
   6408 
   6409   // Named store.
   6410   HValue* value = Pop();
   6411   HValue* object = Pop();
   6412 
   6413   Literal* key = prop->key()->AsLiteral();
   6414   Handle<String> name = Handle<String>::cast(key->value());
   6415   DCHECK(!name.is_null());
   6416 
   6417   HValue* access = BuildNamedAccess(STORE, ast_id, return_id, expr, slot,
   6418                                     object, name, value, is_uninitialized);
   6419   if (access == NULL) return;
   6420 
   6421   if (!ast_context()->IsEffect()) Push(value);
   6422   if (access->IsInstruction()) AddInstruction(HInstruction::cast(access));
   6423   if (access->HasObservableSideEffects()) {
   6424     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6425   }
   6426   if (!ast_context()->IsEffect()) Drop(1);
   6427   return ast_context()->ReturnValue(value);
   6428 }
   6429 
   6430 
   6431 void HOptimizedGraphBuilder::HandlePropertyAssignment(Assignment* expr) {
   6432   Property* prop = expr->target()->AsProperty();
   6433   DCHECK(prop != NULL);
   6434   CHECK_ALIVE(VisitForValue(prop->obj()));
   6435   if (!prop->key()->IsPropertyName()) {
   6436     CHECK_ALIVE(VisitForValue(prop->key()));
   6437   }
   6438   CHECK_ALIVE(VisitForValue(expr->value()));
   6439   BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
   6440              expr->AssignmentId(), expr->IsUninitialized());
   6441 }
   6442 
   6443 HInstruction* HOptimizedGraphBuilder::InlineGlobalPropertyStore(
   6444     LookupIterator* it, HValue* value, BailoutId ast_id) {
   6445   Handle<PropertyCell> cell = it->GetPropertyCell();
   6446   top_info()->dependencies()->AssumePropertyCell(cell);
   6447   auto cell_type = it->property_details().cell_type();
   6448   if (cell_type == PropertyCellType::kConstant ||
   6449       cell_type == PropertyCellType::kUndefined) {
   6450     Handle<Object> constant(cell->value(), isolate());
   6451     if (value->IsConstant()) {
   6452       HConstant* c_value = HConstant::cast(value);
   6453       if (!constant.is_identical_to(c_value->handle(isolate()))) {
   6454         Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment,
   6455                          Deoptimizer::EAGER);
   6456       }
   6457     } else {
   6458       HValue* c_constant = Add<HConstant>(constant);
   6459       IfBuilder builder(this);
   6460       if (constant->IsNumber()) {
   6461         builder.If<HCompareNumericAndBranch>(value, c_constant, Token::EQ);
   6462       } else {
   6463         builder.If<HCompareObjectEqAndBranch>(value, c_constant);
   6464       }
   6465       builder.Then();
   6466       builder.Else();
   6467       Add<HDeoptimize>(DeoptimizeReason::kConstantGlobalVariableAssignment,
   6468                        Deoptimizer::EAGER);
   6469       builder.End();
   6470     }
   6471   }
   6472   HConstant* cell_constant = Add<HConstant>(cell);
   6473   auto access = HObjectAccess::ForPropertyCellValue();
   6474   if (cell_type == PropertyCellType::kConstantType) {
   6475     switch (cell->GetConstantType()) {
   6476       case PropertyCellConstantType::kSmi:
   6477         access = access.WithRepresentation(Representation::Smi());
   6478         break;
   6479       case PropertyCellConstantType::kStableMap: {
   6480         // First check that the previous value of the {cell} still has the
   6481         // map that we are about to check the new {value} for. If not, then
   6482         // the stable map assumption was invalidated and we cannot continue
   6483         // with the optimized code.
   6484         Handle<HeapObject> cell_value(HeapObject::cast(cell->value()));
   6485         Handle<Map> cell_value_map(cell_value->map());
   6486         if (!cell_value_map->is_stable()) {
   6487           Bailout(kUnstableConstantTypeHeapObject);
   6488           return nullptr;
   6489         }
   6490         top_info()->dependencies()->AssumeMapStable(cell_value_map);
   6491         // Now check that the new {value} is a HeapObject with the same map
   6492         Add<HCheckHeapObject>(value);
   6493         value = Add<HCheckMaps>(value, cell_value_map);
   6494         access = access.WithRepresentation(Representation::HeapObject());
   6495         break;
   6496       }
   6497     }
   6498   }
   6499   HInstruction* instr = New<HStoreNamedField>(cell_constant, access, value);
   6500   instr->ClearChangesFlag(kInobjectFields);
   6501   instr->SetChangesFlag(kGlobalVars);
   6502   return instr;
   6503 }
   6504 
   6505 // Because not every expression has a position and there is not common
   6506 // superclass of Assignment and CountOperation, we cannot just pass the
   6507 // owning expression instead of position and ast_id separately.
   6508 void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
   6509     Variable* var, HValue* value, FeedbackVectorSlot slot, BailoutId ast_id) {
   6510   Handle<JSGlobalObject> global(current_info()->global_object());
   6511 
   6512   // Lookup in script contexts.
   6513   {
   6514     Handle<ScriptContextTable> script_contexts(
   6515         global->native_context()->script_context_table());
   6516     ScriptContextTable::LookupResult lookup;
   6517     if (ScriptContextTable::Lookup(script_contexts, var->name(), &lookup)) {
   6518       if (lookup.mode == CONST) {
   6519         return Bailout(kNonInitializerAssignmentToConst);
   6520       }
   6521       Handle<Context> script_context =
   6522           ScriptContextTable::GetContext(script_contexts, lookup.context_index);
   6523 
   6524       Handle<Object> current_value =
   6525           FixedArray::get(*script_context, lookup.slot_index, isolate());
   6526 
   6527       // If the values is not the hole, it will stay initialized,
   6528       // so no need to generate a check.
   6529       if (current_value->IsTheHole(isolate())) {
   6530         return Bailout(kReferenceToUninitializedVariable);
   6531       }
   6532 
   6533       HStoreNamedField* instr = Add<HStoreNamedField>(
   6534           Add<HConstant>(script_context),
   6535           HObjectAccess::ForContextSlot(lookup.slot_index), value);
   6536       USE(instr);
   6537       DCHECK(instr->HasObservableSideEffects());
   6538       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6539       return;
   6540     }
   6541   }
   6542 
   6543   LookupIterator it(global, var->name(), LookupIterator::OWN);
   6544   if (CanInlineGlobalPropertyAccess(var, &it, STORE)) {
   6545     HInstruction* instr = InlineGlobalPropertyStore(&it, value, ast_id);
   6546     if (!instr) return;
   6547     AddInstruction(instr);
   6548     if (instr->HasObservableSideEffects()) {
   6549       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6550     }
   6551   } else {
   6552     HValue* global_object = Add<HLoadNamedField>(
   6553         BuildGetNativeContext(), nullptr,
   6554         HObjectAccess::ForContextSlot(Context::EXTENSION_INDEX));
   6555     Handle<TypeFeedbackVector> vector =
   6556         handle(current_feedback_vector(), isolate());
   6557     HValue* name = Add<HConstant>(var->name());
   6558     HValue* vector_value = Add<HConstant>(vector);
   6559     HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
   6560     Callable callable = CodeFactory::StoreICInOptimizedCode(
   6561         isolate(), function_language_mode());
   6562     HValue* stub = Add<HConstant>(callable.code());
   6563     HValue* values[] = {global_object, name, value, slot_value, vector_value};
   6564     HCallWithDescriptor* instr = Add<HCallWithDescriptor>(
   6565         Code::STORE_IC, stub, 0, callable.descriptor(), ArrayVector(values));
   6566     USE(instr);
   6567     DCHECK(instr->HasObservableSideEffects());
   6568     Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   6569   }
   6570 }
   6571 
   6572 
   6573 void HOptimizedGraphBuilder::HandleCompoundAssignment(Assignment* expr) {
   6574   Expression* target = expr->target();
   6575   VariableProxy* proxy = target->AsVariableProxy();
   6576   Property* prop = target->AsProperty();
   6577   DCHECK(proxy == NULL || prop == NULL);
   6578 
   6579   // We have a second position recorded in the FullCodeGenerator to have
   6580   // type feedback for the binary operation.
   6581   BinaryOperation* operation = expr->binary_operation();
   6582 
   6583   if (proxy != NULL) {
   6584     Variable* var = proxy->var();
   6585     if (var->mode() == LET)  {
   6586       return Bailout(kUnsupportedLetCompoundAssignment);
   6587     }
   6588 
   6589     CHECK_ALIVE(VisitForValue(operation));
   6590 
   6591     switch (var->location()) {
   6592       case VariableLocation::UNALLOCATED:
   6593         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
   6594                                        expr->AssignmentId());
   6595         break;
   6596 
   6597       case VariableLocation::PARAMETER:
   6598       case VariableLocation::LOCAL:
   6599         if (var->mode() == CONST) {
   6600           return Bailout(kNonInitializerAssignmentToConst);
   6601         }
   6602         BindIfLive(var, Top());
   6603         break;
   6604 
   6605       case VariableLocation::CONTEXT: {
   6606         // Bail out if we try to mutate a parameter value in a function
   6607         // using the arguments object.  We do not (yet) correctly handle the
   6608         // arguments property of the function.
   6609         if (current_info()->scope()->arguments() != NULL) {
   6610           // Parameters will be allocated to context slots.  We have no
   6611           // direct way to detect that the variable is a parameter so we do
   6612           // a linear search of the parameter variables.
   6613           int count = current_info()->scope()->num_parameters();
   6614           for (int i = 0; i < count; ++i) {
   6615             if (var == current_info()->scope()->parameter(i)) {
   6616               Bailout(kAssignmentToParameterFunctionUsesArgumentsObject);
   6617             }
   6618           }
   6619         }
   6620 
   6621         HStoreContextSlot::Mode mode;
   6622 
   6623         switch (var->mode()) {
   6624           case LET:
   6625             mode = HStoreContextSlot::kCheckDeoptimize;
   6626             break;
   6627           case CONST:
   6628             if (var->throw_on_const_assignment(function_language_mode())) {
   6629               return Bailout(kNonInitializerAssignmentToConst);
   6630             } else {
   6631               return ast_context()->ReturnValue(Pop());
   6632             }
   6633           default:
   6634             mode = HStoreContextSlot::kNoCheck;
   6635         }
   6636 
   6637         HValue* context = BuildContextChainWalk(var);
   6638         HStoreContextSlot* instr = Add<HStoreContextSlot>(
   6639             context, var->index(), mode, Top());
   6640         if (instr->HasObservableSideEffects()) {
   6641           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   6642         }
   6643         break;
   6644       }
   6645 
   6646       case VariableLocation::LOOKUP:
   6647         return Bailout(kCompoundAssignmentToLookupSlot);
   6648 
   6649       case VariableLocation::MODULE:
   6650         UNREACHABLE();
   6651     }
   6652     return ast_context()->ReturnValue(Pop());
   6653 
   6654   } else if (prop != NULL) {
   6655     CHECK_ALIVE(VisitForValue(prop->obj()));
   6656     HValue* object = Top();
   6657     HValue* key = NULL;
   6658     if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
   6659       CHECK_ALIVE(VisitForValue(prop->key()));
   6660       key = Top();
   6661     }
   6662 
   6663     CHECK_ALIVE(PushLoad(prop, object, key));
   6664 
   6665     CHECK_ALIVE(VisitForValue(expr->value()));
   6666     HValue* right = Pop();
   6667     HValue* left = Pop();
   6668 
   6669     Push(BuildBinaryOperation(operation, left, right, PUSH_BEFORE_SIMULATE));
   6670 
   6671     BuildStore(expr, prop, expr->AssignmentSlot(), expr->id(),
   6672                expr->AssignmentId(), expr->IsUninitialized());
   6673   } else {
   6674     return Bailout(kInvalidLhsInCompoundAssignment);
   6675   }
   6676 }
   6677 
   6678 
   6679 void HOptimizedGraphBuilder::VisitAssignment(Assignment* expr) {
   6680   DCHECK(!HasStackOverflow());
   6681   DCHECK(current_block() != NULL);
   6682   DCHECK(current_block()->HasPredecessor());
   6683 
   6684   VariableProxy* proxy = expr->target()->AsVariableProxy();
   6685   Property* prop = expr->target()->AsProperty();
   6686   DCHECK(proxy == NULL || prop == NULL);
   6687 
   6688   if (expr->is_compound()) {
   6689     HandleCompoundAssignment(expr);
   6690     return;
   6691   }
   6692 
   6693   if (prop != NULL) {
   6694     HandlePropertyAssignment(expr);
   6695   } else if (proxy != NULL) {
   6696     Variable* var = proxy->var();
   6697 
   6698     if (var->mode() == CONST) {
   6699       if (expr->op() != Token::INIT) {
   6700         if (var->throw_on_const_assignment(function_language_mode())) {
   6701           return Bailout(kNonInitializerAssignmentToConst);
   6702         } else {
   6703           CHECK_ALIVE(VisitForValue(expr->value()));
   6704           return ast_context()->ReturnValue(Pop());
   6705         }
   6706       }
   6707     }
   6708 
   6709     // Handle the assignment.
   6710     switch (var->location()) {
   6711       case VariableLocation::UNALLOCATED:
   6712         CHECK_ALIVE(VisitForValue(expr->value()));
   6713         HandleGlobalVariableAssignment(var, Top(), expr->AssignmentSlot(),
   6714                                        expr->AssignmentId());
   6715         return ast_context()->ReturnValue(Pop());
   6716 
   6717       case VariableLocation::PARAMETER:
   6718       case VariableLocation::LOCAL: {
   6719         // Perform an initialization check for let declared variables
   6720         // or parameters.
   6721         if (var->mode() == LET && expr->op() == Token::ASSIGN) {
   6722           HValue* env_value = environment()->Lookup(var);
   6723           if (env_value == graph()->GetConstantHole()) {
   6724             return Bailout(kAssignmentToLetVariableBeforeInitialization);
   6725           }
   6726         }
   6727         // We do not allow the arguments object to occur in a context where it
   6728         // may escape, but assignments to stack-allocated locals are
   6729         // permitted.
   6730         CHECK_ALIVE(VisitForValue(expr->value(), ARGUMENTS_ALLOWED));
   6731         HValue* value = Pop();
   6732         BindIfLive(var, value);
   6733         return ast_context()->ReturnValue(value);
   6734       }
   6735 
   6736       case VariableLocation::CONTEXT: {
   6737         // Bail out if we try to mutate a parameter value in a function using
   6738         // the arguments object.  We do not (yet) correctly handle the
   6739         // arguments property of the function.
   6740         if (current_info()->scope()->arguments() != NULL) {
   6741           // Parameters will rewrite to context slots.  We have no direct way
   6742           // to detect that the variable is a parameter.
   6743           int count = current_info()->scope()->num_parameters();
   6744           for (int i = 0; i < count; ++i) {
   6745             if (var == current_info()->scope()->parameter(i)) {
   6746               return Bailout(kAssignmentToParameterInArgumentsObject);
   6747             }
   6748           }
   6749         }
   6750 
   6751         CHECK_ALIVE(VisitForValue(expr->value()));
   6752         HStoreContextSlot::Mode mode;
   6753         if (expr->op() == Token::ASSIGN) {
   6754           switch (var->mode()) {
   6755             case LET:
   6756               mode = HStoreContextSlot::kCheckDeoptimize;
   6757               break;
   6758             case CONST:
   6759               // If we reached this point, the only possibility
   6760               // is a sloppy assignment to a function name.
   6761               DCHECK(function_language_mode() == SLOPPY &&
   6762                      !var->throw_on_const_assignment(SLOPPY));
   6763               return ast_context()->ReturnValue(Pop());
   6764             default:
   6765               mode = HStoreContextSlot::kNoCheck;
   6766           }
   6767         } else {
   6768           DCHECK_EQ(Token::INIT, expr->op());
   6769           mode = HStoreContextSlot::kNoCheck;
   6770         }
   6771 
   6772         HValue* context = BuildContextChainWalk(var);
   6773         HStoreContextSlot* instr = Add<HStoreContextSlot>(
   6774             context, var->index(), mode, Top());
   6775         if (instr->HasObservableSideEffects()) {
   6776           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   6777         }
   6778         return ast_context()->ReturnValue(Pop());
   6779       }
   6780 
   6781       case VariableLocation::LOOKUP:
   6782         return Bailout(kAssignmentToLOOKUPVariable);
   6783 
   6784       case VariableLocation::MODULE:
   6785         UNREACHABLE();
   6786     }
   6787   } else {
   6788     return Bailout(kInvalidLeftHandSideInAssignment);
   6789   }
   6790 }
   6791 
   6792 
   6793 void HOptimizedGraphBuilder::VisitYield(Yield* expr) {
   6794   // Generators are not optimized, so we should never get here.
   6795   UNREACHABLE();
   6796 }
   6797 
   6798 
   6799 void HOptimizedGraphBuilder::VisitThrow(Throw* expr) {
   6800   DCHECK(!HasStackOverflow());
   6801   DCHECK(current_block() != NULL);
   6802   DCHECK(current_block()->HasPredecessor());
   6803   if (!ast_context()->IsEffect()) {
   6804     // The parser turns invalid left-hand sides in assignments into throw
   6805     // statements, which may not be in effect contexts. We might still try
   6806     // to optimize such functions; bail out now if we do.
   6807     return Bailout(kInvalidLeftHandSideInAssignment);
   6808   }
   6809   CHECK_ALIVE(VisitForValue(expr->exception()));
   6810 
   6811   HValue* value = environment()->Pop();
   6812   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   6813   Add<HPushArguments>(value);
   6814   Add<HCallRuntime>(Runtime::FunctionForId(Runtime::kThrow), 1);
   6815   Add<HSimulate>(expr->id());
   6816 
   6817   // If the throw definitely exits the function, we can finish with a dummy
   6818   // control flow at this point.  This is not the case if the throw is inside
   6819   // an inlined function which may be replaced.
   6820   if (call_context() == NULL) {
   6821     FinishExitCurrentBlock(New<HAbnormalExit>());
   6822   }
   6823 }
   6824 
   6825 
   6826 HInstruction* HGraphBuilder::AddLoadStringInstanceType(HValue* string) {
   6827   if (string->IsConstant()) {
   6828     HConstant* c_string = HConstant::cast(string);
   6829     if (c_string->HasStringValue()) {
   6830       return Add<HConstant>(c_string->StringValue()->map()->instance_type());
   6831     }
   6832   }
   6833   return Add<HLoadNamedField>(
   6834       Add<HLoadNamedField>(string, nullptr, HObjectAccess::ForMap()), nullptr,
   6835       HObjectAccess::ForMapInstanceType());
   6836 }
   6837 
   6838 
   6839 HInstruction* HGraphBuilder::AddLoadStringLength(HValue* string) {
   6840   return AddInstruction(BuildLoadStringLength(string));
   6841 }
   6842 
   6843 
   6844 HInstruction* HGraphBuilder::BuildLoadStringLength(HValue* string) {
   6845   if (string->IsConstant()) {
   6846     HConstant* c_string = HConstant::cast(string);
   6847     if (c_string->HasStringValue()) {
   6848       return New<HConstant>(c_string->StringValue()->length());
   6849     }
   6850   }
   6851   return New<HLoadNamedField>(string, nullptr,
   6852                               HObjectAccess::ForStringLength());
   6853 }
   6854 
   6855 
   6856 HInstruction* HOptimizedGraphBuilder::BuildNamedGeneric(
   6857     PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
   6858     HValue* object, Handle<Name> name, HValue* value, bool is_uninitialized) {
   6859   if (is_uninitialized) {
   6860     Add<HDeoptimize>(
   6861         DeoptimizeReason::kInsufficientTypeFeedbackForGenericNamedAccess,
   6862         Deoptimizer::SOFT);
   6863   }
   6864   Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate());
   6865 
   6866   HValue* key = Add<HConstant>(name);
   6867   HValue* vector_value = Add<HConstant>(vector);
   6868   HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
   6869 
   6870   if (access_type == LOAD) {
   6871     HValue* values[] = {object, key, slot_value, vector_value};
   6872     if (!expr->AsProperty()->key()->IsPropertyName()) {
   6873       // It's possible that a keyed load of a constant string was converted
   6874       // to a named load. Here, at the last minute, we need to make sure to
   6875       // use a generic Keyed Load if we are using the type vector, because
   6876       // it has to share information with full code.
   6877       Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
   6878       HValue* stub = Add<HConstant>(callable.code());
   6879       HCallWithDescriptor* result =
   6880           New<HCallWithDescriptor>(Code::KEYED_LOAD_IC, stub, 0,
   6881                                    callable.descriptor(), ArrayVector(values));
   6882       return result;
   6883     }
   6884     Callable callable = CodeFactory::LoadICInOptimizedCode(isolate());
   6885     HValue* stub = Add<HConstant>(callable.code());
   6886     HCallWithDescriptor* result = New<HCallWithDescriptor>(
   6887         Code::LOAD_IC, stub, 0, callable.descriptor(), ArrayVector(values));
   6888     return result;
   6889 
   6890   } else {
   6891     HValue* values[] = {object, key, value, slot_value, vector_value};
   6892     if (vector->GetKind(slot) == FeedbackVectorSlotKind::KEYED_STORE_IC) {
   6893       // It's possible that a keyed store of a constant string was converted
   6894       // to a named store. Here, at the last minute, we need to make sure to
   6895       // use a generic Keyed Store if we are using the type vector, because
   6896       // it has to share information with full code.
   6897       Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
   6898           isolate(), function_language_mode());
   6899       HValue* stub = Add<HConstant>(callable.code());
   6900       HCallWithDescriptor* result =
   6901           New<HCallWithDescriptor>(Code::KEYED_STORE_IC, stub, 0,
   6902                                    callable.descriptor(), ArrayVector(values));
   6903       return result;
   6904     }
   6905     Callable callable = CodeFactory::StoreICInOptimizedCode(
   6906         isolate(), function_language_mode());
   6907     HValue* stub = Add<HConstant>(callable.code());
   6908     HCallWithDescriptor* result = New<HCallWithDescriptor>(
   6909         Code::STORE_IC, stub, 0, callable.descriptor(), ArrayVector(values));
   6910     return result;
   6911   }
   6912 }
   6913 
   6914 
   6915 HInstruction* HOptimizedGraphBuilder::BuildKeyedGeneric(
   6916     PropertyAccessType access_type, Expression* expr, FeedbackVectorSlot slot,
   6917     HValue* object, HValue* key, HValue* value) {
   6918   Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate());
   6919   HValue* vector_value = Add<HConstant>(vector);
   6920   HValue* slot_value = Add<HConstant>(vector->GetIndex(slot));
   6921 
   6922   if (access_type == LOAD) {
   6923     HValue* values[] = {object, key, slot_value, vector_value};
   6924 
   6925     Callable callable = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
   6926     HValue* stub = Add<HConstant>(callable.code());
   6927     HCallWithDescriptor* result =
   6928         New<HCallWithDescriptor>(Code::KEYED_LOAD_IC, stub, 0,
   6929                                  callable.descriptor(), ArrayVector(values));
   6930     return result;
   6931   } else {
   6932     HValue* values[] = {object, key, value, slot_value, vector_value};
   6933 
   6934     Callable callable = CodeFactory::KeyedStoreICInOptimizedCode(
   6935         isolate(), function_language_mode());
   6936     HValue* stub = Add<HConstant>(callable.code());
   6937     HCallWithDescriptor* result =
   6938         New<HCallWithDescriptor>(Code::KEYED_STORE_IC, stub, 0,
   6939                                  callable.descriptor(), ArrayVector(values));
   6940     return result;
   6941   }
   6942 }
   6943 
   6944 
   6945 LoadKeyedHoleMode HOptimizedGraphBuilder::BuildKeyedHoleMode(Handle<Map> map) {
   6946   // Loads from a "stock" fast holey double arrays can elide the hole check.
   6947   // Loads from a "stock" fast holey array can convert the hole to undefined
   6948   // with impunity.
   6949   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
   6950   bool holey_double_elements =
   6951       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_DOUBLE_ELEMENTS);
   6952   bool holey_elements =
   6953       *map == isolate()->get_initial_js_array_map(FAST_HOLEY_ELEMENTS);
   6954   if ((holey_double_elements || holey_elements) &&
   6955       isolate()->IsFastArrayConstructorPrototypeChainIntact()) {
   6956     load_mode =
   6957         holey_double_elements ? ALLOW_RETURN_HOLE : CONVERT_HOLE_TO_UNDEFINED;
   6958 
   6959     Handle<JSObject> prototype(JSObject::cast(map->prototype()), isolate());
   6960     Handle<JSObject> object_prototype = isolate()->initial_object_prototype();
   6961     BuildCheckPrototypeMaps(prototype, object_prototype);
   6962     graph()->MarkDependsOnEmptyArrayProtoElements();
   6963   }
   6964   return load_mode;
   6965 }
   6966 
   6967 
   6968 HInstruction* HOptimizedGraphBuilder::BuildMonomorphicElementAccess(
   6969     HValue* object,
   6970     HValue* key,
   6971     HValue* val,
   6972     HValue* dependency,
   6973     Handle<Map> map,
   6974     PropertyAccessType access_type,
   6975     KeyedAccessStoreMode store_mode) {
   6976   HCheckMaps* checked_object = Add<HCheckMaps>(object, map, dependency);
   6977 
   6978   if (access_type == STORE && map->prototype()->IsJSObject()) {
   6979     // monomorphic stores need a prototype chain check because shape
   6980     // changes could allow callbacks on elements in the chain that
   6981     // aren't compatible with monomorphic keyed stores.
   6982     PrototypeIterator iter(map);
   6983     JSObject* holder = NULL;
   6984     while (!iter.IsAtEnd()) {
   6985       // JSProxies can't occur here because we wouldn't have installed a
   6986       // non-generic IC if there were any.
   6987       holder = *PrototypeIterator::GetCurrent<JSObject>(iter);
   6988       iter.Advance();
   6989     }
   6990     DCHECK(holder && holder->IsJSObject());
   6991 
   6992     BuildCheckPrototypeMaps(handle(JSObject::cast(map->prototype())),
   6993                             Handle<JSObject>(holder));
   6994   }
   6995 
   6996   LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
   6997   return BuildUncheckedMonomorphicElementAccess(
   6998       checked_object, key, val,
   6999       map->instance_type() == JS_ARRAY_TYPE,
   7000       map->elements_kind(), access_type,
   7001       load_mode, store_mode);
   7002 }
   7003 
   7004 
   7005 static bool CanInlineElementAccess(Handle<Map> map) {
   7006   return map->IsJSObjectMap() &&
   7007          (map->has_fast_elements() || map->has_fixed_typed_array_elements()) &&
   7008          !map->has_indexed_interceptor() && !map->is_access_check_needed();
   7009 }
   7010 
   7011 
   7012 HInstruction* HOptimizedGraphBuilder::TryBuildConsolidatedElementLoad(
   7013     HValue* object,
   7014     HValue* key,
   7015     HValue* val,
   7016     SmallMapList* maps) {
   7017   // For polymorphic loads of similar elements kinds (i.e. all tagged or all
   7018   // double), always use the "worst case" code without a transition.  This is
   7019   // much faster than transitioning the elements to the worst case, trading a
   7020   // HTransitionElements for a HCheckMaps, and avoiding mutation of the array.
   7021   bool has_double_maps = false;
   7022   bool has_smi_or_object_maps = false;
   7023   bool has_js_array_access = false;
   7024   bool has_non_js_array_access = false;
   7025   bool has_seen_holey_elements = false;
   7026   Handle<Map> most_general_consolidated_map;
   7027   for (int i = 0; i < maps->length(); ++i) {
   7028     Handle<Map> map = maps->at(i);
   7029     if (!CanInlineElementAccess(map)) return NULL;
   7030     // Don't allow mixing of JSArrays with JSObjects.
   7031     if (map->instance_type() == JS_ARRAY_TYPE) {
   7032       if (has_non_js_array_access) return NULL;
   7033       has_js_array_access = true;
   7034     } else if (has_js_array_access) {
   7035       return NULL;
   7036     } else {
   7037       has_non_js_array_access = true;
   7038     }
   7039     // Don't allow mixed, incompatible elements kinds.
   7040     if (map->has_fast_double_elements()) {
   7041       if (has_smi_or_object_maps) return NULL;
   7042       has_double_maps = true;
   7043     } else if (map->has_fast_smi_or_object_elements()) {
   7044       if (has_double_maps) return NULL;
   7045       has_smi_or_object_maps = true;
   7046     } else {
   7047       return NULL;
   7048     }
   7049     // Remember if we've ever seen holey elements.
   7050     if (IsHoleyElementsKind(map->elements_kind())) {
   7051       has_seen_holey_elements = true;
   7052     }
   7053     // Remember the most general elements kind, the code for its load will
   7054     // properly handle all of the more specific cases.
   7055     if ((i == 0) || IsMoreGeneralElementsKindTransition(
   7056             most_general_consolidated_map->elements_kind(),
   7057             map->elements_kind())) {
   7058       most_general_consolidated_map = map;
   7059     }
   7060   }
   7061   if (!has_double_maps && !has_smi_or_object_maps) return NULL;
   7062 
   7063   HCheckMaps* checked_object = Add<HCheckMaps>(object, maps);
   7064   // FAST_ELEMENTS is considered more general than FAST_HOLEY_SMI_ELEMENTS.
   7065   // If we've seen both, the consolidated load must use FAST_HOLEY_ELEMENTS.
   7066   ElementsKind consolidated_elements_kind = has_seen_holey_elements
   7067       ? GetHoleyElementsKind(most_general_consolidated_map->elements_kind())
   7068       : most_general_consolidated_map->elements_kind();
   7069   LoadKeyedHoleMode load_mode = NEVER_RETURN_HOLE;
   7070   if (has_seen_holey_elements) {
   7071     // Make sure that all of the maps we are handling have the initial array
   7072     // prototype.
   7073     bool saw_non_array_prototype = false;
   7074     for (int i = 0; i < maps->length(); ++i) {
   7075       Handle<Map> map = maps->at(i);
   7076       if (map->prototype() != *isolate()->initial_array_prototype()) {
   7077         // We can't guarantee that loading the hole is safe. The prototype may
   7078         // have an element at this position.
   7079         saw_non_array_prototype = true;
   7080         break;
   7081       }
   7082     }
   7083 
   7084     if (!saw_non_array_prototype) {
   7085       Handle<Map> holey_map = handle(
   7086           isolate()->get_initial_js_array_map(consolidated_elements_kind));
   7087       load_mode = BuildKeyedHoleMode(holey_map);
   7088       if (load_mode != NEVER_RETURN_HOLE) {
   7089         for (int i = 0; i < maps->length(); ++i) {
   7090           Handle<Map> map = maps->at(i);
   7091           // The prototype check was already done for the holey map in
   7092           // BuildKeyedHoleMode.
   7093           if (!map.is_identical_to(holey_map)) {
   7094             Handle<JSObject> prototype(JSObject::cast(map->prototype()),
   7095                                        isolate());
   7096             Handle<JSObject> object_prototype =
   7097                 isolate()->initial_object_prototype();
   7098             BuildCheckPrototypeMaps(prototype, object_prototype);
   7099           }
   7100         }
   7101       }
   7102     }
   7103   }
   7104   HInstruction* instr = BuildUncheckedMonomorphicElementAccess(
   7105       checked_object, key, val,
   7106       most_general_consolidated_map->instance_type() == JS_ARRAY_TYPE,
   7107       consolidated_elements_kind, LOAD, load_mode, STANDARD_STORE);
   7108   return instr;
   7109 }
   7110 
   7111 
   7112 HValue* HOptimizedGraphBuilder::HandlePolymorphicElementAccess(
   7113     Expression* expr, FeedbackVectorSlot slot, HValue* object, HValue* key,
   7114     HValue* val, SmallMapList* maps, PropertyAccessType access_type,
   7115     KeyedAccessStoreMode store_mode, bool* has_side_effects) {
   7116   *has_side_effects = false;
   7117   BuildCheckHeapObject(object);
   7118 
   7119   if (access_type == LOAD) {
   7120     HInstruction* consolidated_load =
   7121         TryBuildConsolidatedElementLoad(object, key, val, maps);
   7122     if (consolidated_load != NULL) {
   7123       *has_side_effects |= consolidated_load->HasObservableSideEffects();
   7124       return consolidated_load;
   7125     }
   7126   }
   7127 
   7128   // Elements_kind transition support.
   7129   MapHandleList transition_target(maps->length());
   7130   // Collect possible transition targets.
   7131   MapHandleList possible_transitioned_maps(maps->length());
   7132   for (int i = 0; i < maps->length(); ++i) {
   7133     Handle<Map> map = maps->at(i);
   7134     // Loads from strings or loads with a mix of string and non-string maps
   7135     // shouldn't be handled polymorphically.
   7136     DCHECK(access_type != LOAD || !map->IsStringMap());
   7137     ElementsKind elements_kind = map->elements_kind();
   7138     if (CanInlineElementAccess(map) && IsFastElementsKind(elements_kind) &&
   7139         elements_kind != GetInitialFastElementsKind()) {
   7140       possible_transitioned_maps.Add(map);
   7141     }
   7142     if (IsSloppyArgumentsElements(elements_kind)) {
   7143       HInstruction* result =
   7144           BuildKeyedGeneric(access_type, expr, slot, object, key, val);
   7145       *has_side_effects = result->HasObservableSideEffects();
   7146       return AddInstruction(result);
   7147     }
   7148   }
   7149   // Get transition target for each map (NULL == no transition).
   7150   for (int i = 0; i < maps->length(); ++i) {
   7151     Handle<Map> map = maps->at(i);
   7152     Map* transitioned_map =
   7153         map->FindElementsKindTransitionedMap(&possible_transitioned_maps);
   7154     if (transitioned_map != nullptr) {
   7155       transition_target.Add(handle(transitioned_map));
   7156     } else {
   7157       transition_target.Add(Handle<Map>());
   7158     }
   7159   }
   7160 
   7161   MapHandleList untransitionable_maps(maps->length());
   7162   HTransitionElementsKind* transition = NULL;
   7163   for (int i = 0; i < maps->length(); ++i) {
   7164     Handle<Map> map = maps->at(i);
   7165     DCHECK(map->IsMap());
   7166     if (!transition_target.at(i).is_null()) {
   7167       DCHECK(Map::IsValidElementsTransition(
   7168           map->elements_kind(),
   7169           transition_target.at(i)->elements_kind()));
   7170       transition = Add<HTransitionElementsKind>(object, map,
   7171                                                 transition_target.at(i));
   7172     } else {
   7173       untransitionable_maps.Add(map);
   7174     }
   7175   }
   7176 
   7177   // If only one map is left after transitioning, handle this case
   7178   // monomorphically.
   7179   DCHECK(untransitionable_maps.length() >= 1);
   7180   if (untransitionable_maps.length() == 1) {
   7181     Handle<Map> untransitionable_map = untransitionable_maps[0];
   7182     HInstruction* instr = NULL;
   7183     if (!CanInlineElementAccess(untransitionable_map)) {
   7184       instr = AddInstruction(
   7185           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
   7186     } else {
   7187       instr = BuildMonomorphicElementAccess(
   7188           object, key, val, transition, untransitionable_map, access_type,
   7189           store_mode);
   7190     }
   7191     *has_side_effects |= instr->HasObservableSideEffects();
   7192     return access_type == STORE ? val : instr;
   7193   }
   7194 
   7195   HBasicBlock* join = graph()->CreateBasicBlock();
   7196 
   7197   for (int i = 0; i < untransitionable_maps.length(); ++i) {
   7198     Handle<Map> map = untransitionable_maps[i];
   7199     ElementsKind elements_kind = map->elements_kind();
   7200     HBasicBlock* this_map = graph()->CreateBasicBlock();
   7201     HBasicBlock* other_map = graph()->CreateBasicBlock();
   7202     HCompareMap* mapcompare =
   7203         New<HCompareMap>(object, map, this_map, other_map);
   7204     FinishCurrentBlock(mapcompare);
   7205 
   7206     set_current_block(this_map);
   7207     HInstruction* access = NULL;
   7208     if (!CanInlineElementAccess(map)) {
   7209       access = AddInstruction(
   7210           BuildKeyedGeneric(access_type, expr, slot, object, key, val));
   7211     } else {
   7212       DCHECK(IsFastElementsKind(elements_kind) ||
   7213              IsFixedTypedArrayElementsKind(elements_kind));
   7214       LoadKeyedHoleMode load_mode = BuildKeyedHoleMode(map);
   7215       // Happily, mapcompare is a checked object.
   7216       access = BuildUncheckedMonomorphicElementAccess(
   7217           mapcompare, key, val,
   7218           map->instance_type() == JS_ARRAY_TYPE,
   7219           elements_kind, access_type,
   7220           load_mode,
   7221           store_mode);
   7222     }
   7223     *has_side_effects |= access->HasObservableSideEffects();
   7224     // The caller will use has_side_effects and add a correct Simulate.
   7225     access->SetFlag(HValue::kHasNoObservableSideEffects);
   7226     if (access_type == LOAD) {
   7227       Push(access);
   7228     }
   7229     NoObservableSideEffectsScope scope(this);
   7230     GotoNoSimulate(join);
   7231     set_current_block(other_map);
   7232   }
   7233 
   7234   // Ensure that we visited at least one map above that goes to join. This is
   7235   // necessary because FinishExitWithHardDeoptimization does an AbnormalExit
   7236   // rather than joining the join block. If this becomes an issue, insert a
   7237   // generic access in the case length() == 0.
   7238   DCHECK(join->predecessors()->length() > 0);
   7239   // Deopt if none of the cases matched.
   7240   NoObservableSideEffectsScope scope(this);
   7241   FinishExitWithHardDeoptimization(
   7242       DeoptimizeReason::kUnknownMapInPolymorphicElementAccess);
   7243   set_current_block(join);
   7244   return access_type == STORE ? val : Pop();
   7245 }
   7246 
   7247 HValue* HOptimizedGraphBuilder::HandleKeyedElementAccess(
   7248     HValue* obj, HValue* key, HValue* val, Expression* expr,
   7249     FeedbackVectorSlot slot, BailoutId ast_id, BailoutId return_id,
   7250     PropertyAccessType access_type, bool* has_side_effects) {
   7251   // A keyed name access with type feedback may contain the name.
   7252   Handle<TypeFeedbackVector> vector =
   7253       handle(current_feedback_vector(), isolate());
   7254   HValue* expected_key = key;
   7255   if (!key->ActualValue()->IsConstant()) {
   7256     Name* name = nullptr;
   7257     if (access_type == LOAD) {
   7258       KeyedLoadICNexus nexus(vector, slot);
   7259       name = nexus.FindFirstName();
   7260     } else {
   7261       KeyedStoreICNexus nexus(vector, slot);
   7262       name = nexus.FindFirstName();
   7263     }
   7264     if (name != nullptr) {
   7265       Handle<Name> handle_name(name);
   7266       expected_key = Add<HConstant>(handle_name);
   7267       // We need a check against the key.
   7268       bool in_new_space = isolate()->heap()->InNewSpace(*handle_name);
   7269       Unique<Name> unique_name = Unique<Name>::CreateUninitialized(handle_name);
   7270       Add<HCheckValue>(key, unique_name, in_new_space);
   7271     }
   7272   }
   7273   if (expected_key->ActualValue()->IsConstant()) {
   7274     Handle<Object> constant =
   7275         HConstant::cast(expected_key->ActualValue())->handle(isolate());
   7276     uint32_t array_index;
   7277     if ((constant->IsString() &&
   7278          !Handle<String>::cast(constant)->AsArrayIndex(&array_index)) ||
   7279         constant->IsSymbol()) {
   7280       if (!constant->IsUniqueName()) {
   7281         constant = isolate()->factory()->InternalizeString(
   7282             Handle<String>::cast(constant));
   7283       }
   7284       HValue* access =
   7285           BuildNamedAccess(access_type, ast_id, return_id, expr, slot, obj,
   7286                            Handle<Name>::cast(constant), val, false);
   7287       if (access == NULL || access->IsPhi() ||
   7288           HInstruction::cast(access)->IsLinked()) {
   7289         *has_side_effects = false;
   7290       } else {
   7291         HInstruction* instr = HInstruction::cast(access);
   7292         AddInstruction(instr);
   7293         *has_side_effects = instr->HasObservableSideEffects();
   7294       }
   7295       return access;
   7296     }
   7297   }
   7298 
   7299   DCHECK(!expr->IsPropertyName());
   7300   HInstruction* instr = NULL;
   7301 
   7302   SmallMapList* maps;
   7303   bool monomorphic = ComputeReceiverTypes(expr, obj, &maps, this);
   7304 
   7305   bool force_generic = false;
   7306   if (expr->GetKeyType() == PROPERTY) {
   7307     // Non-Generic accesses assume that elements are being accessed, and will
   7308     // deopt for non-index keys, which the IC knows will occur.
   7309     // TODO(jkummerow): Consider adding proper support for property accesses.
   7310     force_generic = true;
   7311     monomorphic = false;
   7312   } else if (access_type == STORE &&
   7313              (monomorphic || (maps != NULL && !maps->is_empty()))) {
   7314     // Stores can't be mono/polymorphic if their prototype chain has dictionary
   7315     // elements. However a receiver map that has dictionary elements itself
   7316     // should be left to normal mono/poly behavior (the other maps may benefit
   7317     // from highly optimized stores).
   7318     for (int i = 0; i < maps->length(); i++) {
   7319       Handle<Map> current_map = maps->at(i);
   7320       if (current_map->DictionaryElementsInPrototypeChainOnly()) {
   7321         force_generic = true;
   7322         monomorphic = false;
   7323         break;
   7324       }
   7325     }
   7326   } else if (access_type == LOAD && !monomorphic &&
   7327              (maps != NULL && !maps->is_empty())) {
   7328     // Polymorphic loads have to go generic if any of the maps are strings.
   7329     // If some, but not all of the maps are strings, we should go generic
   7330     // because polymorphic access wants to key on ElementsKind and isn't
   7331     // compatible with strings.
   7332     for (int i = 0; i < maps->length(); i++) {
   7333       Handle<Map> current_map = maps->at(i);
   7334       if (current_map->IsStringMap()) {
   7335         force_generic = true;
   7336         break;
   7337       }
   7338     }
   7339   }
   7340 
   7341   if (monomorphic) {
   7342     Handle<Map> map = maps->first();
   7343     if (!CanInlineElementAccess(map)) {
   7344       instr = AddInstruction(
   7345           BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
   7346     } else {
   7347       BuildCheckHeapObject(obj);
   7348       instr = BuildMonomorphicElementAccess(
   7349           obj, key, val, NULL, map, access_type, expr->GetStoreMode());
   7350     }
   7351   } else if (!force_generic && (maps != NULL && !maps->is_empty())) {
   7352     return HandlePolymorphicElementAccess(expr, slot, obj, key, val, maps,
   7353                                           access_type, expr->GetStoreMode(),
   7354                                           has_side_effects);
   7355   } else {
   7356     if (access_type == STORE) {
   7357       if (expr->IsAssignment() &&
   7358           expr->AsAssignment()->HasNoTypeInformation()) {
   7359         Add<HDeoptimize>(
   7360             DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess,
   7361             Deoptimizer::SOFT);
   7362       }
   7363     } else {
   7364       if (expr->AsProperty()->HasNoTypeInformation()) {
   7365         Add<HDeoptimize>(
   7366             DeoptimizeReason::kInsufficientTypeFeedbackForGenericKeyedAccess,
   7367             Deoptimizer::SOFT);
   7368       }
   7369     }
   7370     instr = AddInstruction(
   7371         BuildKeyedGeneric(access_type, expr, slot, obj, key, val));
   7372   }
   7373   *has_side_effects = instr->HasObservableSideEffects();
   7374   return instr;
   7375 }
   7376 
   7377 
   7378 void HOptimizedGraphBuilder::EnsureArgumentsArePushedForAccess() {
   7379   // Outermost function already has arguments on the stack.
   7380   if (function_state()->outer() == NULL) return;
   7381 
   7382   if (function_state()->arguments_pushed()) return;
   7383 
   7384   // Push arguments when entering inlined function.
   7385   HEnterInlined* entry = function_state()->entry();
   7386   entry->set_arguments_pushed();
   7387 
   7388   HArgumentsObject* arguments = entry->arguments_object();
   7389   const ZoneList<HValue*>* arguments_values = arguments->arguments_values();
   7390 
   7391   HInstruction* insert_after = entry;
   7392   for (int i = 0; i < arguments_values->length(); i++) {
   7393     HValue* argument = arguments_values->at(i);
   7394     HInstruction* push_argument = New<HPushArguments>(argument);
   7395     push_argument->InsertAfter(insert_after);
   7396     insert_after = push_argument;
   7397   }
   7398 
   7399   HArgumentsElements* arguments_elements = New<HArgumentsElements>(true);
   7400   arguments_elements->ClearFlag(HValue::kUseGVN);
   7401   arguments_elements->InsertAfter(insert_after);
   7402   function_state()->set_arguments_elements(arguments_elements);
   7403 }
   7404 
   7405 bool HOptimizedGraphBuilder::IsAnyParameterContextAllocated() {
   7406   int count = current_info()->scope()->num_parameters();
   7407   for (int i = 0; i < count; ++i) {
   7408     if (current_info()->scope()->parameter(i)->location() ==
   7409         VariableLocation::CONTEXT) {
   7410       return true;
   7411     }
   7412   }
   7413   return false;
   7414 }
   7415 
   7416 bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
   7417   VariableProxy* proxy = expr->obj()->AsVariableProxy();
   7418   if (proxy == NULL) return false;
   7419   if (!proxy->var()->IsStackAllocated()) return false;
   7420   if (!environment()->Lookup(proxy->var())->CheckFlag(HValue::kIsArguments)) {
   7421     return false;
   7422   }
   7423 
   7424   HInstruction* result = NULL;
   7425   if (expr->key()->IsPropertyName()) {
   7426     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
   7427     if (!String::Equals(name, isolate()->factory()->length_string())) {
   7428       return false;
   7429     }
   7430 
   7431     // Make sure we visit the arguments object so that the liveness analysis
   7432     // still records the access.
   7433     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->obj(), ARGUMENTS_ALLOWED), true);
   7434     Drop(1);
   7435 
   7436     if (function_state()->outer() == NULL) {
   7437       HInstruction* elements = Add<HArgumentsElements>(false);
   7438       result = New<HArgumentsLength>(elements);
   7439     } else {
   7440       // Number of arguments without receiver.
   7441       int argument_count = environment()->
   7442           arguments_environment()->parameter_count() - 1;
   7443       result = New<HConstant>(argument_count);
   7444     }
   7445   } else {
   7446     // We need to take into account the KEYED_LOAD_IC feedback to guard the
   7447     // HBoundsCheck instructions below.
   7448     if (!expr->IsMonomorphic() && !expr->IsUninitialized()) return false;
   7449     if (IsAnyParameterContextAllocated()) return false;
   7450     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->obj(), ARGUMENTS_ALLOWED), true);
   7451     CHECK_ALIVE_OR_RETURN(VisitForValue(expr->key()), true);
   7452     HValue* key = Pop();
   7453     Drop(1);  // Arguments object.
   7454     if (function_state()->outer() == NULL) {
   7455       HInstruction* elements = Add<HArgumentsElements>(false);
   7456       HInstruction* length = Add<HArgumentsLength>(elements);
   7457       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
   7458       result = New<HAccessArgumentsAt>(elements, length, checked_key);
   7459     } else {
   7460       EnsureArgumentsArePushedForAccess();
   7461 
   7462       // Number of arguments without receiver.
   7463       HInstruction* elements = function_state()->arguments_elements();
   7464       int argument_count = environment()->
   7465           arguments_environment()->parameter_count() - 1;
   7466       HInstruction* length = Add<HConstant>(argument_count);
   7467       HInstruction* checked_key = Add<HBoundsCheck>(key, length);
   7468       result = New<HAccessArgumentsAt>(elements, length, checked_key);
   7469     }
   7470   }
   7471   ast_context()->ReturnInstruction(result, expr->id());
   7472   return true;
   7473 }
   7474 
   7475 HValue* HOptimizedGraphBuilder::BuildNamedAccess(
   7476     PropertyAccessType access, BailoutId ast_id, BailoutId return_id,
   7477     Expression* expr, FeedbackVectorSlot slot, HValue* object,
   7478     Handle<Name> name, HValue* value, bool is_uninitialized) {
   7479   SmallMapList* maps;
   7480   ComputeReceiverTypes(expr, object, &maps, this);
   7481   DCHECK(maps != NULL);
   7482 
   7483   // Check for special case: Access via a single map to the global proxy
   7484   // can also be handled monomorphically.
   7485   if (maps->length() > 0) {
   7486     Handle<Object> map_constructor =
   7487         handle(maps->first()->GetConstructor(), isolate());
   7488     if (map_constructor->IsJSFunction()) {
   7489       Handle<Context> map_context =
   7490           handle(Handle<JSFunction>::cast(map_constructor)->context());
   7491       Handle<Context> current_context(current_info()->context());
   7492       bool is_same_context_global_proxy_access =
   7493           maps->length() == 1 &&  // >1 map => fallback to polymorphic
   7494           maps->first()->IsJSGlobalProxyMap() &&
   7495           (*map_context == *current_context);
   7496       if (is_same_context_global_proxy_access) {
   7497         Handle<JSGlobalObject> global_object(current_info()->global_object());
   7498         LookupIterator it(global_object, name, LookupIterator::OWN);
   7499         if (CanInlineGlobalPropertyAccess(&it, access)) {
   7500           BuildCheckHeapObject(object);
   7501           Add<HCheckMaps>(object, maps);
   7502           if (access == LOAD) {
   7503             InlineGlobalPropertyLoad(&it, expr->id());
   7504             return nullptr;
   7505           } else {
   7506             return InlineGlobalPropertyStore(&it, value, expr->id());
   7507           }
   7508         }
   7509       }
   7510     }
   7511 
   7512     PropertyAccessInfo info(this, access, maps->first(), name);
   7513     if (!info.CanAccessAsMonomorphic(maps)) {
   7514       HandlePolymorphicNamedFieldAccess(access, expr, slot, ast_id, return_id,
   7515                                         object, value, maps, name);
   7516       return NULL;
   7517     }
   7518 
   7519     HValue* checked_object;
   7520     // AstType::Number() is only supported by polymorphic load/call handling.
   7521     DCHECK(!info.IsNumberType());
   7522     BuildCheckHeapObject(object);
   7523     if (AreStringTypes(maps)) {
   7524       checked_object =
   7525           Add<HCheckInstanceType>(object, HCheckInstanceType::IS_STRING);
   7526     } else {
   7527       checked_object = Add<HCheckMaps>(object, maps);
   7528     }
   7529     return BuildMonomorphicAccess(
   7530         &info, object, checked_object, value, ast_id, return_id);
   7531   }
   7532 
   7533   return BuildNamedGeneric(access, expr, slot, object, name, value,
   7534                            is_uninitialized);
   7535 }
   7536 
   7537 
   7538 void HOptimizedGraphBuilder::PushLoad(Property* expr,
   7539                                       HValue* object,
   7540                                       HValue* key) {
   7541   ValueContext for_value(this, ARGUMENTS_NOT_ALLOWED);
   7542   Push(object);
   7543   if (key != NULL) Push(key);
   7544   BuildLoad(expr, expr->LoadId());
   7545 }
   7546 
   7547 
   7548 void HOptimizedGraphBuilder::BuildLoad(Property* expr,
   7549                                        BailoutId ast_id) {
   7550   HInstruction* instr = NULL;
   7551   if (expr->IsStringAccess() && expr->GetKeyType() == ELEMENT) {
   7552     HValue* index = Pop();
   7553     HValue* string = Pop();
   7554     HInstruction* char_code = BuildStringCharCodeAt(string, index);
   7555     AddInstruction(char_code);
   7556     instr = NewUncasted<HStringCharFromCode>(char_code);
   7557 
   7558   } else if (expr->key()->IsPropertyName()) {
   7559     Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
   7560     HValue* object = Pop();
   7561 
   7562     HValue* value = BuildNamedAccess(LOAD, ast_id, expr->LoadId(), expr,
   7563                                      expr->PropertyFeedbackSlot(), object, name,
   7564                                      NULL, expr->IsUninitialized());
   7565     if (value == NULL) return;
   7566     if (value->IsPhi()) return ast_context()->ReturnValue(value);
   7567     instr = HInstruction::cast(value);
   7568     if (instr->IsLinked()) return ast_context()->ReturnValue(instr);
   7569 
   7570   } else {
   7571     HValue* key = Pop();
   7572     HValue* obj = Pop();
   7573 
   7574     bool has_side_effects = false;
   7575     HValue* load = HandleKeyedElementAccess(
   7576         obj, key, NULL, expr, expr->PropertyFeedbackSlot(), ast_id,
   7577         expr->LoadId(), LOAD, &has_side_effects);
   7578     if (has_side_effects) {
   7579       if (ast_context()->IsEffect()) {
   7580         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   7581       } else {
   7582         Push(load);
   7583         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   7584         Drop(1);
   7585       }
   7586     }
   7587     if (load == NULL) return;
   7588     return ast_context()->ReturnValue(load);
   7589   }
   7590   return ast_context()->ReturnInstruction(instr, ast_id);
   7591 }
   7592 
   7593 
   7594 void HOptimizedGraphBuilder::VisitProperty(Property* expr) {
   7595   DCHECK(!HasStackOverflow());
   7596   DCHECK(current_block() != NULL);
   7597   DCHECK(current_block()->HasPredecessor());
   7598 
   7599   if (TryArgumentsAccess(expr)) return;
   7600 
   7601   CHECK_ALIVE(VisitForValue(expr->obj()));
   7602   if (!expr->key()->IsPropertyName() || expr->IsStringAccess()) {
   7603     CHECK_ALIVE(VisitForValue(expr->key()));
   7604   }
   7605 
   7606   BuildLoad(expr, expr->id());
   7607 }
   7608 
   7609 
   7610 HInstruction* HGraphBuilder::BuildConstantMapCheck(Handle<JSObject> constant) {
   7611   HCheckMaps* check = Add<HCheckMaps>(
   7612       Add<HConstant>(constant), handle(constant->map()));
   7613   check->ClearDependsOnFlag(kElementsKind);
   7614   return check;
   7615 }
   7616 
   7617 
   7618 HInstruction* HGraphBuilder::BuildCheckPrototypeMaps(Handle<JSObject> prototype,
   7619                                                      Handle<JSObject> holder) {
   7620   PrototypeIterator iter(isolate(), prototype, kStartAtReceiver);
   7621   while (holder.is_null() ||
   7622          !PrototypeIterator::GetCurrent(iter).is_identical_to(holder)) {
   7623     BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
   7624     iter.Advance();
   7625     if (iter.IsAtEnd()) {
   7626       return NULL;
   7627     }
   7628   }
   7629   return BuildConstantMapCheck(PrototypeIterator::GetCurrent<JSObject>(iter));
   7630 }
   7631 
   7632 
   7633 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder,
   7634                                                    Handle<Map> receiver_map) {
   7635   if (!holder.is_null()) {
   7636     Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
   7637     BuildCheckPrototypeMaps(prototype, holder);
   7638   }
   7639 }
   7640 
   7641 void HOptimizedGraphBuilder::BuildEnsureCallable(HValue* object) {
   7642   NoObservableSideEffectsScope scope(this);
   7643   const Runtime::Function* throw_called_non_callable =
   7644       Runtime::FunctionForId(Runtime::kThrowCalledNonCallable);
   7645 
   7646   IfBuilder is_not_function(this);
   7647   HValue* smi_check = is_not_function.If<HIsSmiAndBranch>(object);
   7648   is_not_function.Or();
   7649   HValue* map = AddLoadMap(object, smi_check);
   7650   HValue* bit_field =
   7651       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapBitField());
   7652   HValue* bit_field_masked = AddUncasted<HBitwise>(
   7653       Token::BIT_AND, bit_field, Add<HConstant>(1 << Map::kIsCallable));
   7654   is_not_function.IfNot<HCompareNumericAndBranch>(
   7655       bit_field_masked, Add<HConstant>(1 << Map::kIsCallable), Token::EQ);
   7656   is_not_function.Then();
   7657   {
   7658     Add<HPushArguments>(object);
   7659     Add<HCallRuntime>(throw_called_non_callable, 1);
   7660   }
   7661   is_not_function.End();
   7662 }
   7663 
   7664 HInstruction* HOptimizedGraphBuilder::NewCallFunction(
   7665     HValue* function, int argument_count, TailCallMode syntactic_tail_call_mode,
   7666     ConvertReceiverMode convert_mode, TailCallMode tail_call_mode) {
   7667   if (syntactic_tail_call_mode == TailCallMode::kAllow) {
   7668     BuildEnsureCallable(function);
   7669   } else {
   7670     DCHECK_EQ(TailCallMode::kDisallow, tail_call_mode);
   7671   }
   7672   HValue* arity = Add<HConstant>(argument_count - 1);
   7673 
   7674   HValue* op_vals[] = {function, arity};
   7675 
   7676   Callable callable =
   7677       CodeFactory::Call(isolate(), convert_mode, tail_call_mode);
   7678   HConstant* stub = Add<HConstant>(callable.code());
   7679 
   7680   return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
   7681                                   ArrayVector(op_vals),
   7682                                   syntactic_tail_call_mode);
   7683 }
   7684 
   7685 HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC(
   7686     HValue* function, int argument_count, TailCallMode syntactic_tail_call_mode,
   7687     ConvertReceiverMode convert_mode, TailCallMode tail_call_mode,
   7688     FeedbackVectorSlot slot) {
   7689   if (syntactic_tail_call_mode == TailCallMode::kAllow) {
   7690     BuildEnsureCallable(function);
   7691   } else {
   7692     DCHECK_EQ(TailCallMode::kDisallow, tail_call_mode);
   7693   }
   7694   int arity = argument_count - 1;
   7695   Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate());
   7696   HValue* arity_val = Add<HConstant>(arity);
   7697   HValue* index_val = Add<HConstant>(vector->GetIndex(slot));
   7698   HValue* vector_val = Add<HConstant>(vector);
   7699 
   7700   HValue* op_vals[] = {function, arity_val, index_val, vector_val};
   7701   Callable callable = CodeFactory::CallICInOptimizedCode(
   7702       isolate(), convert_mode, tail_call_mode);
   7703   HConstant* stub = Add<HConstant>(callable.code());
   7704 
   7705   return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(),
   7706                                   ArrayVector(op_vals),
   7707                                   syntactic_tail_call_mode);
   7708 }
   7709 
   7710 HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction(
   7711     Handle<JSFunction> function, int argument_count,
   7712     TailCallMode syntactic_tail_call_mode, TailCallMode tail_call_mode) {
   7713   HValue* target = Add<HConstant>(function);
   7714   return New<HInvokeFunction>(target, function, argument_count,
   7715                               syntactic_tail_call_mode, tail_call_mode);
   7716 }
   7717 
   7718 
   7719 class FunctionSorter {
   7720  public:
   7721   explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0)
   7722       : index_(index), ticks_(ticks), size_(size) {}
   7723 
   7724   int index() const { return index_; }
   7725   int ticks() const { return ticks_; }
   7726   int size() const { return size_; }
   7727 
   7728  private:
   7729   int index_;
   7730   int ticks_;
   7731   int size_;
   7732 };
   7733 
   7734 
   7735 inline bool operator<(const FunctionSorter& lhs, const FunctionSorter& rhs) {
   7736   int diff = lhs.ticks() - rhs.ticks();
   7737   if (diff != 0) return diff > 0;
   7738   return lhs.size() < rhs.size();
   7739 }
   7740 
   7741 
   7742 void HOptimizedGraphBuilder::HandlePolymorphicCallNamed(Call* expr,
   7743                                                         HValue* receiver,
   7744                                                         SmallMapList* maps,
   7745                                                         Handle<String> name) {
   7746   int argument_count = expr->arguments()->length() + 1;  // Includes receiver.
   7747   FunctionSorter order[kMaxCallPolymorphism];
   7748 
   7749   bool handle_smi = false;
   7750   bool handled_string = false;
   7751   int ordered_functions = 0;
   7752 
   7753   TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
   7754   TailCallMode tail_call_mode =
   7755       function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
   7756 
   7757   int i;
   7758   for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism;
   7759        ++i) {
   7760     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
   7761     if (info.CanAccessMonomorphic() && info.IsDataConstant() &&
   7762         info.constant()->IsJSFunction()) {
   7763       if (info.IsStringType()) {
   7764         if (handled_string) continue;
   7765         handled_string = true;
   7766       }
   7767       Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
   7768       if (info.IsNumberType()) {
   7769         handle_smi = true;
   7770       }
   7771       expr->set_target(target);
   7772       order[ordered_functions++] = FunctionSorter(
   7773           i, target->shared()->profiler_ticks(), InliningAstSize(target));
   7774     }
   7775   }
   7776 
   7777   std::sort(order, order + ordered_functions);
   7778 
   7779   if (i < maps->length()) {
   7780     maps->Clear();
   7781     ordered_functions = -1;
   7782   }
   7783 
   7784   HBasicBlock* number_block = NULL;
   7785   HBasicBlock* join = NULL;
   7786   handled_string = false;
   7787   int count = 0;
   7788 
   7789   for (int fn = 0; fn < ordered_functions; ++fn) {
   7790     int i = order[fn].index();
   7791     PropertyAccessInfo info(this, LOAD, maps->at(i), name);
   7792     if (info.IsStringType()) {
   7793       if (handled_string) continue;
   7794       handled_string = true;
   7795     }
   7796     // Reloads the target.
   7797     info.CanAccessMonomorphic();
   7798     Handle<JSFunction> target = Handle<JSFunction>::cast(info.constant());
   7799 
   7800     expr->set_target(target);
   7801     if (count == 0) {
   7802       // Only needed once.
   7803       join = graph()->CreateBasicBlock();
   7804       if (handle_smi) {
   7805         HBasicBlock* empty_smi_block = graph()->CreateBasicBlock();
   7806         HBasicBlock* not_smi_block = graph()->CreateBasicBlock();
   7807         number_block = graph()->CreateBasicBlock();
   7808         FinishCurrentBlock(New<HIsSmiAndBranch>(
   7809                 receiver, empty_smi_block, not_smi_block));
   7810         GotoNoSimulate(empty_smi_block, number_block);
   7811         set_current_block(not_smi_block);
   7812       } else {
   7813         BuildCheckHeapObject(receiver);
   7814       }
   7815     }
   7816     ++count;
   7817     HBasicBlock* if_true = graph()->CreateBasicBlock();
   7818     HBasicBlock* if_false = graph()->CreateBasicBlock();
   7819     HUnaryControlInstruction* compare;
   7820 
   7821     Handle<Map> map = info.map();
   7822     if (info.IsNumberType()) {
   7823       Handle<Map> heap_number_map = isolate()->factory()->heap_number_map();
   7824       compare = New<HCompareMap>(receiver, heap_number_map, if_true, if_false);
   7825     } else if (info.IsStringType()) {
   7826       compare = New<HIsStringAndBranch>(receiver, if_true, if_false);
   7827     } else {
   7828       compare = New<HCompareMap>(receiver, map, if_true, if_false);
   7829     }
   7830     FinishCurrentBlock(compare);
   7831 
   7832     if (info.IsNumberType()) {
   7833       GotoNoSimulate(if_true, number_block);
   7834       if_true = number_block;
   7835     }
   7836 
   7837     set_current_block(if_true);
   7838 
   7839     AddCheckPrototypeMaps(info.holder(), map);
   7840 
   7841     HValue* function = Add<HConstant>(expr->target());
   7842     environment()->SetExpressionStackAt(0, function);
   7843     Push(receiver);
   7844     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   7845     bool needs_wrapping = info.NeedsWrappingFor(target);
   7846     bool try_inline = FLAG_polymorphic_inlining && !needs_wrapping;
   7847     if (FLAG_trace_inlining && try_inline) {
   7848       Handle<JSFunction> caller = current_info()->closure();
   7849       std::unique_ptr<char[]> caller_name =
   7850           caller->shared()->DebugName()->ToCString();
   7851       PrintF("Trying to inline the polymorphic call to %s from %s\n",
   7852              name->ToCString().get(),
   7853              caller_name.get());
   7854     }
   7855     if (try_inline && TryInlineCall(expr)) {
   7856       // Trying to inline will signal that we should bailout from the
   7857       // entire compilation by setting stack overflow on the visitor.
   7858       if (HasStackOverflow()) return;
   7859     } else {
   7860       // Since HWrapReceiver currently cannot actually wrap numbers and strings,
   7861       // use the regular call builtin for method calls to wrap the receiver.
   7862       // TODO(verwaest): Support creation of value wrappers directly in
   7863       // HWrapReceiver.
   7864       HInstruction* call =
   7865           needs_wrapping
   7866               ? NewCallFunction(
   7867                     function, argument_count, syntactic_tail_call_mode,
   7868                     ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode)
   7869               : NewCallConstantFunction(target, argument_count,
   7870                                         syntactic_tail_call_mode,
   7871                                         tail_call_mode);
   7872       PushArgumentsFromEnvironment(argument_count);
   7873       AddInstruction(call);
   7874       Drop(1);  // Drop the function.
   7875       if (!ast_context()->IsEffect()) Push(call);
   7876     }
   7877 
   7878     if (current_block() != NULL) Goto(join);
   7879     set_current_block(if_false);
   7880   }
   7881 
   7882   // Finish up.  Unconditionally deoptimize if we've handled all the maps we
   7883   // know about and do not want to handle ones we've never seen.  Otherwise
   7884   // use a generic IC.
   7885   if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) {
   7886     FinishExitWithHardDeoptimization(
   7887         DeoptimizeReason::kUnknownMapInPolymorphicCall);
   7888   } else {
   7889     Property* prop = expr->expression()->AsProperty();
   7890     HInstruction* function =
   7891         BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver,
   7892                           name, NULL, prop->IsUninitialized());
   7893     AddInstruction(function);
   7894     Push(function);
   7895     AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE);
   7896 
   7897     environment()->SetExpressionStackAt(1, function);
   7898     environment()->SetExpressionStackAt(0, receiver);
   7899     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   7900 
   7901     HInstruction* call = NewCallFunction(
   7902         function, argument_count, syntactic_tail_call_mode,
   7903         ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode);
   7904 
   7905     PushArgumentsFromEnvironment(argument_count);
   7906 
   7907     Drop(1);  // Function.
   7908 
   7909     if (join != NULL) {
   7910       AddInstruction(call);
   7911       if (!ast_context()->IsEffect()) Push(call);
   7912       Goto(join);
   7913     } else {
   7914       return ast_context()->ReturnInstruction(call, expr->id());
   7915     }
   7916   }
   7917 
   7918   // We assume that control flow is always live after an expression.  So
   7919   // even without predecessors to the join block, we set it as the exit
   7920   // block and continue by adding instructions there.
   7921   DCHECK(join != NULL);
   7922   if (join->HasPredecessor()) {
   7923     set_current_block(join);
   7924     join->SetJoinId(expr->id());
   7925     if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop());
   7926   } else {
   7927     set_current_block(NULL);
   7928   }
   7929 }
   7930 
   7931 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target,
   7932                                          Handle<JSFunction> caller,
   7933                                          const char* reason,
   7934                                          TailCallMode tail_call_mode) {
   7935   if (FLAG_trace_inlining) {
   7936     std::unique_ptr<char[]> target_name =
   7937         target->shared()->DebugName()->ToCString();
   7938     std::unique_ptr<char[]> caller_name =
   7939         caller->shared()->DebugName()->ToCString();
   7940     if (reason == NULL) {
   7941       const char* call_mode =
   7942           tail_call_mode == TailCallMode::kAllow ? "tail called" : "called";
   7943       PrintF("Inlined %s %s from %s.\n", target_name.get(), call_mode,
   7944              caller_name.get());
   7945     } else {
   7946       PrintF("Did not inline %s called from %s (%s).\n",
   7947              target_name.get(), caller_name.get(), reason);
   7948     }
   7949   }
   7950 }
   7951 
   7952 
   7953 static const int kNotInlinable = 1000000000;
   7954 
   7955 
   7956 int HOptimizedGraphBuilder::InliningAstSize(Handle<JSFunction> target) {
   7957   if (!FLAG_use_inlining) return kNotInlinable;
   7958 
   7959   // Precondition: call is monomorphic and we have found a target with the
   7960   // appropriate arity.
   7961   Handle<JSFunction> caller = current_info()->closure();
   7962   Handle<SharedFunctionInfo> target_shared(target->shared());
   7963 
   7964   // Always inline functions that force inlining.
   7965   if (target_shared->force_inline()) {
   7966     return 0;
   7967   }
   7968   if (target->shared()->IsBuiltin()) {
   7969     return kNotInlinable;
   7970   }
   7971 
   7972   if (target_shared->IsApiFunction()) {
   7973     TraceInline(target, caller, "target is api function");
   7974     return kNotInlinable;
   7975   }
   7976 
   7977   // Do a quick check on source code length to avoid parsing large
   7978   // inlining candidates.
   7979   if (target_shared->SourceSize() >
   7980       Min(FLAG_max_inlined_source_size, kUnlimitedMaxInlinedSourceSize)) {
   7981     TraceInline(target, caller, "target text too big");
   7982     return kNotInlinable;
   7983   }
   7984 
   7985   // Target must be inlineable.
   7986   BailoutReason noopt_reason = target_shared->disable_optimization_reason();
   7987   if (!target_shared->IsInlineable() && noopt_reason != kHydrogenFilter) {
   7988     TraceInline(target, caller, "target not inlineable");
   7989     return kNotInlinable;
   7990   }
   7991   if (noopt_reason != kNoReason && noopt_reason != kHydrogenFilter) {
   7992     TraceInline(target, caller, "target contains unsupported syntax [early]");
   7993     return kNotInlinable;
   7994   }
   7995 
   7996   int nodes_added = target_shared->ast_node_count();
   7997   return nodes_added;
   7998 }
   7999 
   8000 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target,
   8001                                        int arguments_count,
   8002                                        HValue* implicit_return_value,
   8003                                        BailoutId ast_id, BailoutId return_id,
   8004                                        InliningKind inlining_kind,
   8005                                        TailCallMode syntactic_tail_call_mode) {
   8006   if (target->context()->native_context() !=
   8007       top_info()->closure()->context()->native_context()) {
   8008     return false;
   8009   }
   8010   int nodes_added = InliningAstSize(target);
   8011   if (nodes_added == kNotInlinable) return false;
   8012 
   8013   Handle<JSFunction> caller = current_info()->closure();
   8014   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
   8015     TraceInline(target, caller, "target AST is too large [early]");
   8016     return false;
   8017   }
   8018 
   8019   // Don't inline deeper than the maximum number of inlining levels.
   8020   HEnvironment* env = environment();
   8021   int current_level = 1;
   8022   while (env->outer() != NULL) {
   8023     if (current_level == FLAG_max_inlining_levels) {
   8024       TraceInline(target, caller, "inline depth limit reached");
   8025       return false;
   8026     }
   8027     if (env->outer()->frame_type() == JS_FUNCTION) {
   8028       current_level++;
   8029     }
   8030     env = env->outer();
   8031   }
   8032 
   8033   // Don't inline recursive functions.
   8034   for (FunctionState* state = function_state();
   8035        state != NULL;
   8036        state = state->outer()) {
   8037     if (*state->compilation_info()->closure() == *target) {
   8038       TraceInline(target, caller, "target is recursive");
   8039       return false;
   8040     }
   8041   }
   8042 
   8043   // We don't want to add more than a certain number of nodes from inlining.
   8044   // Always inline small methods (<= 10 nodes).
   8045   if (inlined_count_ > Min(FLAG_max_inlined_nodes_cumulative,
   8046                            kUnlimitedMaxInlinedNodesCumulative)) {
   8047     TraceInline(target, caller, "cumulative AST node limit reached");
   8048     return false;
   8049   }
   8050 
   8051   // Parse and allocate variables.
   8052   // Use the same AstValueFactory for creating strings in the sub-compilation
   8053   // step, but don't transfer ownership to target_info.
   8054   Handle<SharedFunctionInfo> target_shared(target->shared());
   8055   ParseInfo parse_info(zone(), target_shared);
   8056   parse_info.set_ast_value_factory(
   8057       top_info()->parse_info()->ast_value_factory());
   8058   parse_info.set_ast_value_factory_owned(false);
   8059 
   8060   CompilationInfo target_info(&parse_info, target);
   8061 
   8062   if (inlining_kind != CONSTRUCT_CALL_RETURN &&
   8063       IsClassConstructor(target_shared->kind())) {
   8064     TraceInline(target, caller, "target is classConstructor");
   8065     return false;
   8066   }
   8067 
   8068   if (target_shared->HasDebugInfo()) {
   8069     TraceInline(target, caller, "target is being debugged");
   8070     return false;
   8071   }
   8072   if (!Compiler::ParseAndAnalyze(target_info.parse_info())) {
   8073     if (target_info.isolate()->has_pending_exception()) {
   8074       // Parse or scope error, never optimize this function.
   8075       SetStackOverflow();
   8076       target_shared->DisableOptimization(kParseScopeError);
   8077     }
   8078     TraceInline(target, caller, "parse failure");
   8079     return false;
   8080   }
   8081   if (target_shared->dont_crankshaft()) {
   8082     TraceInline(target, caller, "ParseAndAnalyze found incompatibility");
   8083     return false;
   8084   }
   8085 
   8086   if (target_info.scope()->NeedsContext()) {
   8087     TraceInline(target, caller, "target has context-allocated variables");
   8088     return false;
   8089   }
   8090 
   8091   if (target_info.scope()->rest_parameter() != nullptr) {
   8092     TraceInline(target, caller, "target uses rest parameters");
   8093     return false;
   8094   }
   8095 
   8096   FunctionLiteral* function = target_info.literal();
   8097 
   8098   // The following conditions must be checked again after re-parsing, because
   8099   // earlier the information might not have been complete due to lazy parsing.
   8100   nodes_added = function->ast_node_count();
   8101   if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) {
   8102     TraceInline(target, caller, "target AST is too large [late]");
   8103     return false;
   8104   }
   8105   if (function->dont_optimize()) {
   8106     TraceInline(target, caller, "target contains unsupported syntax [late]");
   8107     return false;
   8108   }
   8109 
   8110   // If the function uses the arguments object check that inlining of functions
   8111   // with arguments object is enabled and the arguments-variable is
   8112   // stack allocated.
   8113   if (function->scope()->arguments() != NULL) {
   8114     if (!FLAG_inline_arguments) {
   8115       TraceInline(target, caller, "target uses arguments object");
   8116       return false;
   8117     }
   8118   }
   8119 
   8120   // Unsupported variable references present.
   8121   if (function->scope()->this_function_var() != nullptr ||
   8122       function->scope()->new_target_var() != nullptr) {
   8123     TraceInline(target, caller, "target uses new target or this function");
   8124     return false;
   8125   }
   8126 
   8127   // All declarations must be inlineable.
   8128   Declaration::List* decls = target_info.scope()->declarations();
   8129   for (Declaration* decl : *decls) {
   8130     if (decl->IsFunctionDeclaration() ||
   8131         !decl->proxy()->var()->IsStackAllocated()) {
   8132       TraceInline(target, caller, "target has non-trivial declaration");
   8133       return false;
   8134     }
   8135   }
   8136 
   8137   // Generate the deoptimization data for the unoptimized version of
   8138   // the target function if we don't already have it.
   8139   if (!Compiler::EnsureDeoptimizationSupport(&target_info)) {
   8140     TraceInline(target, caller, "could not generate deoptimization info");
   8141     return false;
   8142   }
   8143 
   8144   // Remember that we inlined this function. This needs to be called right
   8145   // after the EnsureDeoptimizationSupport call so that the code flusher
   8146   // does not remove the code with the deoptimization support.
   8147   int inlining_id = top_info()->AddInlinedFunction(target_info.shared_info(),
   8148                                                    source_position());
   8149 
   8150   // ----------------------------------------------------------------
   8151   // After this point, we've made a decision to inline this function (so
   8152   // TryInline should always return true).
   8153 
   8154   // If target was lazily compiled, it's literals array may not yet be set up.
   8155   JSFunction::EnsureLiterals(target);
   8156 
   8157   // Type-check the inlined function.
   8158   DCHECK(target_shared->has_deoptimization_support());
   8159   AstTyper(target_info.isolate(), target_info.zone(), target_info.closure(),
   8160            target_info.scope(), target_info.osr_ast_id(), target_info.literal(),
   8161            &bounds_)
   8162       .Run();
   8163 
   8164   if (is_tracking_positions()) {
   8165     TraceInlinedFunction(target_shared, source_position(), inlining_id);
   8166   }
   8167 
   8168   // Save the pending call context. Set up new one for the inlined function.
   8169   // The function state is new-allocated because we need to delete it
   8170   // in two different places.
   8171   FunctionState* target_state = new FunctionState(
   8172       this, &target_info, inlining_kind, inlining_id,
   8173       function_state()->ComputeTailCallMode(syntactic_tail_call_mode));
   8174 
   8175   HConstant* undefined = graph()->GetConstantUndefined();
   8176 
   8177   HEnvironment* inner_env = environment()->CopyForInlining(
   8178       target, arguments_count, function, undefined,
   8179       function_state()->inlining_kind(), syntactic_tail_call_mode);
   8180 
   8181   HConstant* context = Add<HConstant>(Handle<Context>(target->context()));
   8182   inner_env->BindContext(context);
   8183 
   8184   // Create a dematerialized arguments object for the function, also copy the
   8185   // current arguments values to use them for materialization.
   8186   HEnvironment* arguments_env = inner_env->arguments_environment();
   8187   int parameter_count = arguments_env->parameter_count();
   8188   HArgumentsObject* arguments_object = Add<HArgumentsObject>(parameter_count);
   8189   for (int i = 0; i < parameter_count; i++) {
   8190     arguments_object->AddArgument(arguments_env->Lookup(i), zone());
   8191   }
   8192 
   8193   // If the function uses arguments object then bind bind one.
   8194   if (function->scope()->arguments() != NULL) {
   8195     DCHECK(function->scope()->arguments()->IsStackAllocated());
   8196     inner_env->Bind(function->scope()->arguments(), arguments_object);
   8197   }
   8198 
   8199   // Capture the state before invoking the inlined function for deopt in the
   8200   // inlined function. This simulate has no bailout-id since it's not directly
   8201   // reachable for deopt, and is only used to capture the state. If the simulate
   8202   // becomes reachable by merging, the ast id of the simulate merged into it is
   8203   // adopted.
   8204   Add<HSimulate>(BailoutId::None());
   8205 
   8206   current_block()->UpdateEnvironment(inner_env);
   8207   Scope* saved_scope = scope();
   8208   set_scope(target_info.scope());
   8209   HEnterInlined* enter_inlined = Add<HEnterInlined>(
   8210       return_id, target, context, arguments_count, function,
   8211       function_state()->inlining_kind(), function->scope()->arguments(),
   8212       arguments_object, syntactic_tail_call_mode);
   8213   if (is_tracking_positions()) {
   8214     enter_inlined->set_inlining_id(inlining_id);
   8215   }
   8216 
   8217   function_state()->set_entry(enter_inlined);
   8218 
   8219   VisitDeclarations(target_info.scope()->declarations());
   8220   VisitStatements(function->body());
   8221   set_scope(saved_scope);
   8222   if (HasStackOverflow()) {
   8223     // Bail out if the inline function did, as we cannot residualize a call
   8224     // instead, but do not disable optimization for the outer function.
   8225     TraceInline(target, caller, "inline graph construction failed");
   8226     target_shared->DisableOptimization(kInliningBailedOut);
   8227     current_info()->RetryOptimization(kInliningBailedOut);
   8228     delete target_state;
   8229     return true;
   8230   }
   8231 
   8232   // Update inlined nodes count.
   8233   inlined_count_ += nodes_added;
   8234 
   8235   Handle<Code> unoptimized_code(target_shared->code());
   8236   DCHECK(unoptimized_code->kind() == Code::FUNCTION);
   8237   Handle<TypeFeedbackInfo> type_info(
   8238       TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info()));
   8239   graph()->update_type_change_checksum(type_info->own_type_change_checksum());
   8240 
   8241   TraceInline(target, caller, NULL, syntactic_tail_call_mode);
   8242 
   8243   if (current_block() != NULL) {
   8244     FunctionState* state = function_state();
   8245     if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) {
   8246       // Falling off the end of an inlined construct call. In a test context the
   8247       // return value will always evaluate to true, in a value context the
   8248       // return value is the newly allocated receiver.
   8249       if (call_context()->IsTest()) {
   8250         inlined_test_context()->ReturnValue(graph()->GetConstantTrue());
   8251       } else if (call_context()->IsEffect()) {
   8252         Goto(function_return(), state);
   8253       } else {
   8254         DCHECK(call_context()->IsValue());
   8255         AddLeaveInlined(implicit_return_value, state);
   8256       }
   8257     } else if (state->inlining_kind() == SETTER_CALL_RETURN) {
   8258       // Falling off the end of an inlined setter call. The returned value is
   8259       // never used, the value of an assignment is always the value of the RHS
   8260       // of the assignment.
   8261       if (call_context()->IsTest()) {
   8262         inlined_test_context()->ReturnValue(implicit_return_value);
   8263       } else if (call_context()->IsEffect()) {
   8264         Goto(function_return(), state);
   8265       } else {
   8266         DCHECK(call_context()->IsValue());
   8267         AddLeaveInlined(implicit_return_value, state);
   8268       }
   8269     } else {
   8270       // Falling off the end of a normal inlined function. This basically means
   8271       // returning undefined.
   8272       if (call_context()->IsTest()) {
   8273         inlined_test_context()->ReturnValue(graph()->GetConstantFalse());
   8274       } else if (call_context()->IsEffect()) {
   8275         Goto(function_return(), state);
   8276       } else {
   8277         DCHECK(call_context()->IsValue());
   8278         AddLeaveInlined(undefined, state);
   8279       }
   8280     }
   8281   }
   8282 
   8283   // Fix up the function exits.
   8284   if (inlined_test_context() != NULL) {
   8285     HBasicBlock* if_true = inlined_test_context()->if_true();
   8286     HBasicBlock* if_false = inlined_test_context()->if_false();
   8287 
   8288     HEnterInlined* entry = function_state()->entry();
   8289 
   8290     // Pop the return test context from the expression context stack.
   8291     DCHECK(ast_context() == inlined_test_context());
   8292     ClearInlinedTestContext();
   8293     delete target_state;
   8294 
   8295     // Forward to the real test context.
   8296     if (if_true->HasPredecessor()) {
   8297       entry->RegisterReturnTarget(if_true, zone());
   8298       if_true->SetJoinId(ast_id);
   8299       HBasicBlock* true_target = TestContext::cast(ast_context())->if_true();
   8300       Goto(if_true, true_target, function_state());
   8301     }
   8302     if (if_false->HasPredecessor()) {
   8303       entry->RegisterReturnTarget(if_false, zone());
   8304       if_false->SetJoinId(ast_id);
   8305       HBasicBlock* false_target = TestContext::cast(ast_context())->if_false();
   8306       Goto(if_false, false_target, function_state());
   8307     }
   8308     set_current_block(NULL);
   8309     return true;
   8310 
   8311   } else if (function_return()->HasPredecessor()) {
   8312     function_state()->entry()->RegisterReturnTarget(function_return(), zone());
   8313     function_return()->SetJoinId(ast_id);
   8314     set_current_block(function_return());
   8315   } else {
   8316     set_current_block(NULL);
   8317   }
   8318   delete target_state;
   8319   return true;
   8320 }
   8321 
   8322 
   8323 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) {
   8324   return TryInline(expr->target(), expr->arguments()->length(), NULL,
   8325                    expr->id(), expr->ReturnId(), NORMAL_RETURN,
   8326                    expr->tail_call_mode());
   8327 }
   8328 
   8329 
   8330 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr,
   8331                                                 HValue* implicit_return_value) {
   8332   return TryInline(expr->target(), expr->arguments()->length(),
   8333                    implicit_return_value, expr->id(), expr->ReturnId(),
   8334                    CONSTRUCT_CALL_RETURN, TailCallMode::kDisallow);
   8335 }
   8336 
   8337 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter,
   8338                                              Handle<Map> receiver_map,
   8339                                              BailoutId ast_id,
   8340                                              BailoutId return_id) {
   8341   if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true;
   8342   if (getter->IsJSFunction()) {
   8343     Handle<JSFunction> getter_function = Handle<JSFunction>::cast(getter);
   8344     return TryInlineBuiltinGetterCall(getter_function, receiver_map, ast_id) ||
   8345            TryInline(getter_function, 0, NULL, ast_id, return_id,
   8346                      GETTER_CALL_RETURN, TailCallMode::kDisallow);
   8347   }
   8348   return false;
   8349 }
   8350 
   8351 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter,
   8352                                              Handle<Map> receiver_map,
   8353                                              BailoutId id,
   8354                                              BailoutId assignment_id,
   8355                                              HValue* implicit_return_value) {
   8356   if (TryInlineApiSetter(setter, receiver_map, id)) return true;
   8357   return setter->IsJSFunction() &&
   8358          TryInline(Handle<JSFunction>::cast(setter), 1, implicit_return_value,
   8359                    id, assignment_id, SETTER_CALL_RETURN,
   8360                    TailCallMode::kDisallow);
   8361 }
   8362 
   8363 
   8364 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function,
   8365                                                    Call* expr,
   8366                                                    int arguments_count) {
   8367   return TryInline(function, arguments_count, NULL, expr->id(),
   8368                    expr->ReturnId(), NORMAL_RETURN, expr->tail_call_mode());
   8369 }
   8370 
   8371 
   8372 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) {
   8373   if (!expr->target()->shared()->HasBuiltinFunctionId()) return false;
   8374   BuiltinFunctionId id = expr->target()->shared()->builtin_function_id();
   8375   // We intentionally ignore expr->tail_call_mode() here because builtins
   8376   // we inline here do not observe if they were tail called or not.
   8377   switch (id) {
   8378     case kMathCos:
   8379     case kMathExp:
   8380     case kMathRound:
   8381     case kMathFround:
   8382     case kMathFloor:
   8383     case kMathAbs:
   8384     case kMathSin:
   8385     case kMathSqrt:
   8386     case kMathLog:
   8387     case kMathClz32:
   8388       if (expr->arguments()->length() == 1) {
   8389         HValue* argument = Pop();
   8390         Drop(2);  // Receiver and function.
   8391         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
   8392         ast_context()->ReturnInstruction(op, expr->id());
   8393         return true;
   8394       }
   8395       break;
   8396     case kMathImul:
   8397       if (expr->arguments()->length() == 2) {
   8398         HValue* right = Pop();
   8399         HValue* left = Pop();
   8400         Drop(2);  // Receiver and function.
   8401         HInstruction* op =
   8402             HMul::NewImul(isolate(), zone(), context(), left, right);
   8403         ast_context()->ReturnInstruction(op, expr->id());
   8404         return true;
   8405       }
   8406       break;
   8407     default:
   8408       // Not supported for inlining yet.
   8409       break;
   8410   }
   8411   return false;
   8412 }
   8413 
   8414 
   8415 // static
   8416 bool HOptimizedGraphBuilder::IsReadOnlyLengthDescriptor(
   8417     Handle<Map> jsarray_map) {
   8418   DCHECK(!jsarray_map->is_dictionary_map());
   8419   Isolate* isolate = jsarray_map->GetIsolate();
   8420   Handle<Name> length_string = isolate->factory()->length_string();
   8421   DescriptorArray* descriptors = jsarray_map->instance_descriptors();
   8422   int number =
   8423       descriptors->SearchWithCache(isolate, *length_string, *jsarray_map);
   8424   DCHECK_NE(DescriptorArray::kNotFound, number);
   8425   return descriptors->GetDetails(number).IsReadOnly();
   8426 }
   8427 
   8428 
   8429 // static
   8430 bool HOptimizedGraphBuilder::CanInlineArrayResizeOperation(
   8431     Handle<Map> receiver_map) {
   8432   return !receiver_map.is_null() && receiver_map->prototype()->IsJSObject() &&
   8433          receiver_map->instance_type() == JS_ARRAY_TYPE &&
   8434          IsFastElementsKind(receiver_map->elements_kind()) &&
   8435          !receiver_map->is_dictionary_map() && receiver_map->is_extensible() &&
   8436          (!receiver_map->is_prototype_map() || receiver_map->is_stable()) &&
   8437          !IsReadOnlyLengthDescriptor(receiver_map);
   8438 }
   8439 
   8440 bool HOptimizedGraphBuilder::TryInlineBuiltinGetterCall(
   8441     Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id) {
   8442   if (!function->shared()->HasBuiltinFunctionId()) return false;
   8443   BuiltinFunctionId id = function->shared()->builtin_function_id();
   8444 
   8445   // Try to inline getter calls like DataView.prototype.byteLength/byteOffset
   8446   // as operations in the calling function.
   8447   switch (id) {
   8448     case kDataViewBuffer: {
   8449       if (!receiver_map->IsJSDataViewMap()) return false;
   8450       HObjectAccess access = HObjectAccess::ForMapAndOffset(
   8451           receiver_map, JSDataView::kBufferOffset);
   8452       HValue* object = Pop();  // receiver
   8453       HInstruction* result = New<HLoadNamedField>(object, object, access);
   8454       ast_context()->ReturnInstruction(result, ast_id);
   8455       return true;
   8456     }
   8457     case kDataViewByteLength:
   8458     case kDataViewByteOffset: {
   8459       if (!receiver_map->IsJSDataViewMap()) return false;
   8460       int offset = (id == kDataViewByteLength) ? JSDataView::kByteLengthOffset
   8461                                                : JSDataView::kByteOffsetOffset;
   8462       HObjectAccess access =
   8463           HObjectAccess::ForMapAndOffset(receiver_map, offset);
   8464       HValue* object = Pop();  // receiver
   8465       HValue* checked_object = Add<HCheckArrayBufferNotNeutered>(object);
   8466       HInstruction* result =
   8467           New<HLoadNamedField>(object, checked_object, access);
   8468       ast_context()->ReturnInstruction(result, ast_id);
   8469       return true;
   8470     }
   8471     case kTypedArrayByteLength:
   8472     case kTypedArrayByteOffset:
   8473     case kTypedArrayLength: {
   8474       if (!receiver_map->IsJSTypedArrayMap()) return false;
   8475       int offset = (id == kTypedArrayLength)
   8476                        ? JSTypedArray::kLengthOffset
   8477                        : (id == kTypedArrayByteLength)
   8478                              ? JSTypedArray::kByteLengthOffset
   8479                              : JSTypedArray::kByteOffsetOffset;
   8480       HObjectAccess access =
   8481           HObjectAccess::ForMapAndOffset(receiver_map, offset);
   8482       HValue* object = Pop();  // receiver
   8483       HValue* checked_object = Add<HCheckArrayBufferNotNeutered>(object);
   8484       HInstruction* result =
   8485           New<HLoadNamedField>(object, checked_object, access);
   8486       ast_context()->ReturnInstruction(result, ast_id);
   8487       return true;
   8488     }
   8489     default:
   8490       return false;
   8491   }
   8492 }
   8493 
   8494 bool HOptimizedGraphBuilder::TryInlineBuiltinMethodCall(
   8495     Handle<JSFunction> function, Handle<Map> receiver_map, BailoutId ast_id,
   8496     int args_count_no_receiver) {
   8497   if (!function->shared()->HasBuiltinFunctionId()) return false;
   8498   BuiltinFunctionId id = function->shared()->builtin_function_id();
   8499   int argument_count = args_count_no_receiver + 1;  // Plus receiver.
   8500 
   8501   if (receiver_map.is_null()) {
   8502     HValue* receiver = environment()->ExpressionStackAt(args_count_no_receiver);
   8503     if (receiver->IsConstant() &&
   8504         HConstant::cast(receiver)->handle(isolate())->IsHeapObject()) {
   8505       receiver_map =
   8506           handle(Handle<HeapObject>::cast(
   8507                      HConstant::cast(receiver)->handle(isolate()))->map());
   8508     }
   8509   }
   8510   // Try to inline calls like Math.* as operations in the calling function.
   8511   switch (id) {
   8512     case kObjectHasOwnProperty: {
   8513       // It's not safe to look through the phi for elements if we're compiling
   8514       // for osr.
   8515       if (top_info()->is_osr()) return false;
   8516       if (argument_count != 2) return false;
   8517       HValue* key = Top();
   8518       if (!key->IsLoadKeyed()) return false;
   8519       HValue* elements = HLoadKeyed::cast(key)->elements();
   8520       if (!elements->IsPhi() || elements->OperandCount() != 1) return false;
   8521       if (!elements->OperandAt(0)->IsForInCacheArray()) return false;
   8522       HForInCacheArray* cache = HForInCacheArray::cast(elements->OperandAt(0));
   8523       HValue* receiver = environment()->ExpressionStackAt(1);
   8524       if (!receiver->IsPhi() || receiver->OperandCount() != 1) return false;
   8525       if (cache->enumerable() != receiver->OperandAt(0)) return false;
   8526       Drop(3);  // key, receiver, function
   8527       Add<HCheckMapValue>(receiver, cache->map());
   8528       ast_context()->ReturnValue(graph()->GetConstantTrue());
   8529       return true;
   8530     }
   8531     case kStringCharCodeAt:
   8532     case kStringCharAt:
   8533       if (argument_count == 2) {
   8534         HValue* index = Pop();
   8535         HValue* string = Pop();
   8536         Drop(1);  // Function.
   8537         HInstruction* char_code =
   8538             BuildStringCharCodeAt(string, index);
   8539         if (id == kStringCharCodeAt) {
   8540           ast_context()->ReturnInstruction(char_code, ast_id);
   8541           return true;
   8542         }
   8543         AddInstruction(char_code);
   8544         HInstruction* result = NewUncasted<HStringCharFromCode>(char_code);
   8545         ast_context()->ReturnInstruction(result, ast_id);
   8546         return true;
   8547       }
   8548       break;
   8549     case kStringFromCharCode:
   8550       if (argument_count == 2) {
   8551         HValue* argument = Pop();
   8552         Drop(2);  // Receiver and function.
   8553         argument = AddUncasted<HForceRepresentation>(
   8554             argument, Representation::Integer32());
   8555         argument->SetFlag(HValue::kTruncatingToInt32);
   8556         HInstruction* result = NewUncasted<HStringCharFromCode>(argument);
   8557         ast_context()->ReturnInstruction(result, ast_id);
   8558         return true;
   8559       }
   8560       break;
   8561     case kMathCos:
   8562     case kMathExp:
   8563     case kMathRound:
   8564     case kMathFround:
   8565     case kMathFloor:
   8566     case kMathAbs:
   8567     case kMathSin:
   8568     case kMathSqrt:
   8569     case kMathLog:
   8570     case kMathClz32:
   8571       if (argument_count == 2) {
   8572         HValue* argument = Pop();
   8573         Drop(2);  // Receiver and function.
   8574         HInstruction* op = NewUncasted<HUnaryMathOperation>(argument, id);
   8575         ast_context()->ReturnInstruction(op, ast_id);
   8576         return true;
   8577       }
   8578       break;
   8579     case kMathPow:
   8580       if (argument_count == 3) {
   8581         HValue* right = Pop();
   8582         HValue* left = Pop();
   8583         Drop(2);  // Receiver and function.
   8584         HInstruction* result = NULL;
   8585         // Use sqrt() if exponent is 0.5 or -0.5.
   8586         if (right->IsConstant() && HConstant::cast(right)->HasDoubleValue()) {
   8587           double exponent = HConstant::cast(right)->DoubleValue();
   8588           if (exponent == 0.5) {
   8589             result = NewUncasted<HUnaryMathOperation>(left, kMathPowHalf);
   8590           } else if (exponent == -0.5) {
   8591             HValue* one = graph()->GetConstant1();
   8592             HInstruction* sqrt = AddUncasted<HUnaryMathOperation>(
   8593                 left, kMathPowHalf);
   8594             // MathPowHalf doesn't have side effects so there's no need for
   8595             // an environment simulation here.
   8596             DCHECK(!sqrt->HasObservableSideEffects());
   8597             result = NewUncasted<HDiv>(one, sqrt);
   8598           } else if (exponent == 2.0) {
   8599             result = NewUncasted<HMul>(left, left);
   8600           }
   8601         }
   8602 
   8603         if (result == NULL) {
   8604           result = NewUncasted<HPower>(left, right);
   8605         }
   8606         ast_context()->ReturnInstruction(result, ast_id);
   8607         return true;
   8608       }
   8609       break;
   8610     case kMathMax:
   8611     case kMathMin:
   8612       if (argument_count == 3) {
   8613         HValue* right = Pop();
   8614         HValue* left = Pop();
   8615         Drop(2);  // Receiver and function.
   8616         HMathMinMax::Operation op = (id == kMathMin) ? HMathMinMax::kMathMin
   8617                                                      : HMathMinMax::kMathMax;
   8618         HInstruction* result = NewUncasted<HMathMinMax>(left, right, op);
   8619         ast_context()->ReturnInstruction(result, ast_id);
   8620         return true;
   8621       }
   8622       break;
   8623     case kMathImul:
   8624       if (argument_count == 3) {
   8625         HValue* right = Pop();
   8626         HValue* left = Pop();
   8627         Drop(2);  // Receiver and function.
   8628         HInstruction* result =
   8629             HMul::NewImul(isolate(), zone(), context(), left, right);
   8630         ast_context()->ReturnInstruction(result, ast_id);
   8631         return true;
   8632       }
   8633       break;
   8634     case kArrayPop: {
   8635       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
   8636       ElementsKind elements_kind = receiver_map->elements_kind();
   8637 
   8638       Drop(args_count_no_receiver);
   8639       HValue* result;
   8640       HValue* reduced_length;
   8641       HValue* receiver = Pop();
   8642 
   8643       HValue* checked_object = AddCheckMap(receiver, receiver_map);
   8644       HValue* length =
   8645           Add<HLoadNamedField>(checked_object, nullptr,
   8646                                HObjectAccess::ForArrayLength(elements_kind));
   8647 
   8648       Drop(1);  // Function.
   8649 
   8650       { NoObservableSideEffectsScope scope(this);
   8651         IfBuilder length_checker(this);
   8652 
   8653         HValue* bounds_check = length_checker.If<HCompareNumericAndBranch>(
   8654             length, graph()->GetConstant0(), Token::EQ);
   8655         length_checker.Then();
   8656 
   8657         if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
   8658 
   8659         length_checker.Else();
   8660         HValue* elements = AddLoadElements(checked_object);
   8661         // Ensure that we aren't popping from a copy-on-write array.
   8662         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   8663           elements = BuildCopyElementsOnWrite(checked_object, elements,
   8664                                               elements_kind, length);
   8665         }
   8666         reduced_length = AddUncasted<HSub>(length, graph()->GetConstant1());
   8667         result = AddElementAccess(elements, reduced_length, nullptr,
   8668                                   bounds_check, nullptr, elements_kind, LOAD);
   8669         HValue* hole = IsFastSmiOrObjectElementsKind(elements_kind)
   8670                            ? graph()->GetConstantHole()
   8671                            : Add<HConstant>(HConstant::kHoleNaN);
   8672         if (IsFastSmiOrObjectElementsKind(elements_kind)) {
   8673           elements_kind = FAST_HOLEY_ELEMENTS;
   8674         }
   8675         AddElementAccess(elements, reduced_length, hole, bounds_check, nullptr,
   8676                          elements_kind, STORE);
   8677         Add<HStoreNamedField>(
   8678             checked_object, HObjectAccess::ForArrayLength(elements_kind),
   8679             reduced_length, STORE_TO_INITIALIZED_ENTRY);
   8680 
   8681         if (!ast_context()->IsEffect()) Push(result);
   8682 
   8683         length_checker.End();
   8684       }
   8685       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
   8686       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   8687       if (!ast_context()->IsEffect()) Drop(1);
   8688 
   8689       ast_context()->ReturnValue(result);
   8690       return true;
   8691     }
   8692     case kArrayPush: {
   8693       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
   8694       ElementsKind elements_kind = receiver_map->elements_kind();
   8695 
   8696       // If there may be elements accessors in the prototype chain, the fast
   8697       // inlined version can't be used.
   8698       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8699       // If there currently can be no elements accessors on the prototype chain,
   8700       // it doesn't mean that there won't be any later. Install a full prototype
   8701       // chain check to trap element accessors being installed on the prototype
   8702       // chain, which would cause elements to go to dictionary mode and result
   8703       // in a map change.
   8704       Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype()));
   8705       BuildCheckPrototypeMaps(prototype, Handle<JSObject>());
   8706 
   8707       // Protect against adding elements to the Array prototype, which needs to
   8708       // route through appropriate bottlenecks.
   8709       if (isolate()->IsFastArrayConstructorPrototypeChainIntact() &&
   8710           !prototype->IsJSArray()) {
   8711         return false;
   8712       }
   8713 
   8714       const int argc = args_count_no_receiver;
   8715       if (argc != 1) return false;
   8716 
   8717       HValue* value_to_push = Pop();
   8718       HValue* array = Pop();
   8719       Drop(1);  // Drop function.
   8720 
   8721       HInstruction* new_size = NULL;
   8722       HValue* length = NULL;
   8723 
   8724       {
   8725         NoObservableSideEffectsScope scope(this);
   8726 
   8727         length = Add<HLoadNamedField>(
   8728             array, nullptr, HObjectAccess::ForArrayLength(elements_kind));
   8729 
   8730         new_size = AddUncasted<HAdd>(length, graph()->GetConstant1());
   8731 
   8732         bool is_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
   8733         HValue* checked_array = Add<HCheckMaps>(array, receiver_map);
   8734         BuildUncheckedMonomorphicElementAccess(
   8735             checked_array, length, value_to_push, is_array, elements_kind,
   8736             STORE, NEVER_RETURN_HOLE, STORE_AND_GROW_NO_TRANSITION);
   8737 
   8738         if (!ast_context()->IsEffect()) Push(new_size);
   8739         Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   8740         if (!ast_context()->IsEffect()) Drop(1);
   8741       }
   8742 
   8743       ast_context()->ReturnValue(new_size);
   8744       return true;
   8745     }
   8746     case kArrayShift: {
   8747       if (!CanInlineArrayResizeOperation(receiver_map)) return false;
   8748       ElementsKind kind = receiver_map->elements_kind();
   8749 
   8750       // If there may be elements accessors in the prototype chain, the fast
   8751       // inlined version can't be used.
   8752       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8753 
   8754       // If there currently can be no elements accessors on the prototype chain,
   8755       // it doesn't mean that there won't be any later. Install a full prototype
   8756       // chain check to trap element accessors being installed on the prototype
   8757       // chain, which would cause elements to go to dictionary mode and result
   8758       // in a map change.
   8759       BuildCheckPrototypeMaps(
   8760           handle(JSObject::cast(receiver_map->prototype()), isolate()),
   8761           Handle<JSObject>::null());
   8762 
   8763       // Threshold for fast inlined Array.shift().
   8764       HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16));
   8765 
   8766       Drop(args_count_no_receiver);
   8767       HValue* result;
   8768       HValue* receiver = Pop();
   8769       HValue* checked_object = AddCheckMap(receiver, receiver_map);
   8770       HValue* length = Add<HLoadNamedField>(
   8771           receiver, checked_object, HObjectAccess::ForArrayLength(kind));
   8772 
   8773       Drop(1);  // Function.
   8774       {
   8775         NoObservableSideEffectsScope scope(this);
   8776 
   8777         IfBuilder if_lengthiszero(this);
   8778         HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>(
   8779             length, graph()->GetConstant0(), Token::EQ);
   8780         if_lengthiszero.Then();
   8781         {
   8782           if (!ast_context()->IsEffect()) Push(graph()->GetConstantUndefined());
   8783         }
   8784         if_lengthiszero.Else();
   8785         {
   8786           HValue* elements = AddLoadElements(receiver);
   8787 
   8788           // Check if we can use the fast inlined Array.shift().
   8789           IfBuilder if_inline(this);
   8790           if_inline.If<HCompareNumericAndBranch>(
   8791               length, inline_threshold, Token::LTE);
   8792           if (IsFastSmiOrObjectElementsKind(kind)) {
   8793             // We cannot handle copy-on-write backing stores here.
   8794             if_inline.AndIf<HCompareMap>(
   8795                 elements, isolate()->factory()->fixed_array_map());
   8796           }
   8797           if_inline.Then();
   8798           {
   8799             // Remember the result.
   8800             if (!ast_context()->IsEffect()) {
   8801               Push(AddElementAccess(elements, graph()->GetConstant0(), nullptr,
   8802                                     lengthiszero, nullptr, kind, LOAD));
   8803             }
   8804 
   8805             // Compute the new length.
   8806             HValue* new_length = AddUncasted<HSub>(
   8807                 length, graph()->GetConstant1());
   8808             new_length->ClearFlag(HValue::kCanOverflow);
   8809 
   8810             // Copy the remaining elements.
   8811             LoopBuilder loop(this, context(), LoopBuilder::kPostIncrement);
   8812             {
   8813               HValue* new_key = loop.BeginBody(
   8814                   graph()->GetConstant0(), new_length, Token::LT);
   8815               HValue* key = AddUncasted<HAdd>(new_key, graph()->GetConstant1());
   8816               key->ClearFlag(HValue::kCanOverflow);
   8817               ElementsKind copy_kind =
   8818                   kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
   8819               HValue* element =
   8820                   AddUncasted<HLoadKeyed>(elements, key, lengthiszero, nullptr,
   8821                                           copy_kind, ALLOW_RETURN_HOLE);
   8822               HStoreKeyed* store = Add<HStoreKeyed>(elements, new_key, element,
   8823                                                     nullptr, copy_kind);
   8824               store->SetFlag(HValue::kTruncatingToNumber);
   8825             }
   8826             loop.EndBody();
   8827 
   8828             // Put a hole at the end.
   8829             HValue* hole = IsFastSmiOrObjectElementsKind(kind)
   8830                                ? graph()->GetConstantHole()
   8831                                : Add<HConstant>(HConstant::kHoleNaN);
   8832             if (IsFastSmiOrObjectElementsKind(kind)) kind = FAST_HOLEY_ELEMENTS;
   8833             Add<HStoreKeyed>(elements, new_length, hole, nullptr, kind,
   8834                              INITIALIZING_STORE);
   8835 
   8836             // Remember new length.
   8837             Add<HStoreNamedField>(
   8838                 receiver, HObjectAccess::ForArrayLength(kind),
   8839                 new_length, STORE_TO_INITIALIZED_ENTRY);
   8840           }
   8841           if_inline.Else();
   8842           {
   8843             Add<HPushArguments>(receiver);
   8844             result = AddInstruction(NewCallConstantFunction(
   8845                 function, 1, TailCallMode::kDisallow, TailCallMode::kDisallow));
   8846             if (!ast_context()->IsEffect()) Push(result);
   8847           }
   8848           if_inline.End();
   8849         }
   8850         if_lengthiszero.End();
   8851       }
   8852       result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top();
   8853       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   8854       if (!ast_context()->IsEffect()) Drop(1);
   8855       ast_context()->ReturnValue(result);
   8856       return true;
   8857     }
   8858     case kArrayIndexOf:
   8859     case kArrayLastIndexOf: {
   8860       if (receiver_map.is_null()) return false;
   8861       if (receiver_map->instance_type() != JS_ARRAY_TYPE) return false;
   8862       if (!receiver_map->prototype()->IsJSObject()) return false;
   8863       ElementsKind kind = receiver_map->elements_kind();
   8864       if (!IsFastElementsKind(kind)) return false;
   8865       if (argument_count != 2) return false;
   8866       if (!receiver_map->is_extensible()) return false;
   8867 
   8868       // If there may be elements accessors in the prototype chain, the fast
   8869       // inlined version can't be used.
   8870       if (receiver_map->DictionaryElementsInPrototypeChainOnly()) return false;
   8871 
   8872       // If there currently can be no elements accessors on the prototype chain,
   8873       // it doesn't mean that there won't be any later. Install a full prototype
   8874       // chain check to trap element accessors being installed on the prototype
   8875       // chain, which would cause elements to go to dictionary mode and result
   8876       // in a map change.
   8877       BuildCheckPrototypeMaps(
   8878           handle(JSObject::cast(receiver_map->prototype()), isolate()),
   8879           Handle<JSObject>::null());
   8880 
   8881       HValue* search_element = Pop();
   8882       HValue* receiver = Pop();
   8883       Drop(1);  // Drop function.
   8884 
   8885       ArrayIndexOfMode mode = (id == kArrayIndexOf)
   8886           ? kFirstIndexOf : kLastIndexOf;
   8887       HValue* index = BuildArrayIndexOf(receiver, search_element, kind, mode);
   8888 
   8889       if (!ast_context()->IsEffect()) Push(index);
   8890       Add<HSimulate>(ast_id, REMOVABLE_SIMULATE);
   8891       if (!ast_context()->IsEffect()) Drop(1);
   8892       ast_context()->ReturnValue(index);
   8893       return true;
   8894     }
   8895     default:
   8896       // Not yet supported for inlining.
   8897       break;
   8898   }
   8899   return false;
   8900 }
   8901 
   8902 
   8903 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr,
   8904                                                       HValue* receiver) {
   8905   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
   8906   Handle<JSFunction> function = expr->target();
   8907   int argc = expr->arguments()->length();
   8908   SmallMapList receiver_maps;
   8909   return TryInlineApiCall(function, receiver, &receiver_maps, argc, expr->id(),
   8910                           kCallApiFunction, expr->tail_call_mode());
   8911 }
   8912 
   8913 
   8914 bool HOptimizedGraphBuilder::TryInlineApiMethodCall(
   8915     Call* expr,
   8916     HValue* receiver,
   8917     SmallMapList* receiver_maps) {
   8918   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
   8919   Handle<JSFunction> function = expr->target();
   8920   int argc = expr->arguments()->length();
   8921   return TryInlineApiCall(function, receiver, receiver_maps, argc, expr->id(),
   8922                           kCallApiMethod, expr->tail_call_mode());
   8923 }
   8924 
   8925 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function,
   8926                                                 Handle<Map> receiver_map,
   8927                                                 BailoutId ast_id) {
   8928   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
   8929   SmallMapList receiver_maps(1, zone());
   8930   receiver_maps.Add(receiver_map, zone());
   8931   return TryInlineApiCall(function,
   8932                           NULL,  // Receiver is on expression stack.
   8933                           &receiver_maps, 0, ast_id, kCallApiGetter,
   8934                           TailCallMode::kDisallow);
   8935 }
   8936 
   8937 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function,
   8938                                                 Handle<Map> receiver_map,
   8939                                                 BailoutId ast_id) {
   8940   SmallMapList receiver_maps(1, zone());
   8941   receiver_maps.Add(receiver_map, zone());
   8942   return TryInlineApiCall(function,
   8943                           NULL,  // Receiver is on expression stack.
   8944                           &receiver_maps, 1, ast_id, kCallApiSetter,
   8945                           TailCallMode::kDisallow);
   8946 }
   8947 
   8948 bool HOptimizedGraphBuilder::TryInlineApiCall(
   8949     Handle<Object> function, HValue* receiver, SmallMapList* receiver_maps,
   8950     int argc, BailoutId ast_id, ApiCallType call_type,
   8951     TailCallMode syntactic_tail_call_mode) {
   8952   if (V8_UNLIKELY(FLAG_runtime_stats)) return false;
   8953   if (function->IsJSFunction() &&
   8954       Handle<JSFunction>::cast(function)->context()->native_context() !=
   8955           top_info()->closure()->context()->native_context()) {
   8956     return false;
   8957   }
   8958   if (argc > CallApiCallbackStub::kArgMax) {
   8959     return false;
   8960   }
   8961 
   8962   CallOptimization optimization(function);
   8963   if (!optimization.is_simple_api_call()) return false;
   8964   Handle<Map> holder_map;
   8965   for (int i = 0; i < receiver_maps->length(); ++i) {
   8966     auto map = receiver_maps->at(i);
   8967     // Don't inline calls to receivers requiring accesschecks.
   8968     if (map->is_access_check_needed()) return false;
   8969   }
   8970   if (call_type == kCallApiFunction) {
   8971     // Cannot embed a direct reference to the global proxy map
   8972     // as it maybe dropped on deserialization.
   8973     CHECK(!isolate()->serializer_enabled());
   8974     DCHECK(function->IsJSFunction());
   8975     DCHECK_EQ(0, receiver_maps->length());
   8976     receiver_maps->Add(
   8977         handle(Handle<JSFunction>::cast(function)->global_proxy()->map()),
   8978         zone());
   8979   }
   8980   CallOptimization::HolderLookup holder_lookup =
   8981       CallOptimization::kHolderNotFound;
   8982   Handle<JSObject> api_holder = optimization.LookupHolderOfExpectedType(
   8983       receiver_maps->first(), &holder_lookup);
   8984   if (holder_lookup == CallOptimization::kHolderNotFound) return false;
   8985 
   8986   if (FLAG_trace_inlining) {
   8987     PrintF("Inlining api function ");
   8988     function->ShortPrint();
   8989     PrintF("\n");
   8990   }
   8991 
   8992   bool is_function = false;
   8993   bool is_store = false;
   8994   switch (call_type) {
   8995     case kCallApiFunction:
   8996     case kCallApiMethod:
   8997       // Need to check that none of the receiver maps could have changed.
   8998       Add<HCheckMaps>(receiver, receiver_maps);
   8999       // Need to ensure the chain between receiver and api_holder is intact.
   9000       if (holder_lookup == CallOptimization::kHolderFound) {
   9001         AddCheckPrototypeMaps(api_holder, receiver_maps->first());
   9002       } else {
   9003         DCHECK_EQ(holder_lookup, CallOptimization::kHolderIsReceiver);
   9004       }
   9005       // Includes receiver.
   9006       PushArgumentsFromEnvironment(argc + 1);
   9007       is_function = true;
   9008       break;
   9009     case kCallApiGetter:
   9010       // Receiver and prototype chain cannot have changed.
   9011       DCHECK_EQ(0, argc);
   9012       DCHECK_NULL(receiver);
   9013       // Receiver is on expression stack.
   9014       receiver = Pop();
   9015       Add<HPushArguments>(receiver);
   9016       break;
   9017     case kCallApiSetter:
   9018       {
   9019         is_store = true;
   9020         // Receiver and prototype chain cannot have changed.
   9021         DCHECK_EQ(1, argc);
   9022         DCHECK_NULL(receiver);
   9023         // Receiver and value are on expression stack.
   9024         HValue* value = Pop();
   9025         receiver = Pop();
   9026         Add<HPushArguments>(receiver, value);
   9027         break;
   9028      }
   9029   }
   9030 
   9031   HValue* holder = NULL;
   9032   switch (holder_lookup) {
   9033     case CallOptimization::kHolderFound:
   9034       holder = Add<HConstant>(api_holder);
   9035       break;
   9036     case CallOptimization::kHolderIsReceiver:
   9037       holder = receiver;
   9038       break;
   9039     case CallOptimization::kHolderNotFound:
   9040       UNREACHABLE();
   9041       break;
   9042   }
   9043   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
   9044   Handle<Object> call_data_obj(api_call_info->data(), isolate());
   9045   bool call_data_undefined = call_data_obj->IsUndefined(isolate());
   9046   HValue* call_data = Add<HConstant>(call_data_obj);
   9047   ApiFunction fun(v8::ToCData<Address>(api_call_info->callback()));
   9048   ExternalReference ref = ExternalReference(&fun,
   9049                                             ExternalReference::DIRECT_API_CALL,
   9050                                             isolate());
   9051   HValue* api_function_address = Add<HConstant>(ExternalReference(ref));
   9052 
   9053   HValue* op_vals[] = {Add<HConstant>(function), call_data, holder,
   9054                        api_function_address};
   9055 
   9056   HInstruction* call = nullptr;
   9057   CHECK(argc <= CallApiCallbackStub::kArgMax);
   9058   if (!is_function) {
   9059     CallApiCallbackStub stub(isolate(), is_store, call_data_undefined,
   9060                              !optimization.is_constant_call());
   9061     Handle<Code> code = stub.GetCode();
   9062     HConstant* code_value = Add<HConstant>(code);
   9063     call = New<HCallWithDescriptor>(
   9064         code_value, argc + 1, stub.GetCallInterfaceDescriptor(),
   9065         Vector<HValue*>(op_vals, arraysize(op_vals)), syntactic_tail_call_mode);
   9066   } else {
   9067     CallApiCallbackStub stub(isolate(), argc, call_data_undefined, false);
   9068     Handle<Code> code = stub.GetCode();
   9069     HConstant* code_value = Add<HConstant>(code);
   9070     call = New<HCallWithDescriptor>(
   9071         code_value, argc + 1, stub.GetCallInterfaceDescriptor(),
   9072         Vector<HValue*>(op_vals, arraysize(op_vals)), syntactic_tail_call_mode);
   9073     Drop(1);  // Drop function.
   9074   }
   9075 
   9076   ast_context()->ReturnInstruction(call, ast_id);
   9077   return true;
   9078 }
   9079 
   9080 
   9081 void HOptimizedGraphBuilder::HandleIndirectCall(Call* expr, HValue* function,
   9082                                                 int arguments_count) {
   9083   Handle<JSFunction> known_function;
   9084   int args_count_no_receiver = arguments_count - 1;
   9085   if (function->IsConstant() &&
   9086       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9087     known_function =
   9088         Handle<JSFunction>::cast(HConstant::cast(function)->handle(isolate()));
   9089     if (TryInlineBuiltinMethodCall(known_function, Handle<Map>(), expr->id(),
   9090                                    args_count_no_receiver)) {
   9091       if (FLAG_trace_inlining) {
   9092         PrintF("Inlining builtin ");
   9093         known_function->ShortPrint();
   9094         PrintF("\n");
   9095       }
   9096       return;
   9097     }
   9098 
   9099     if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) {
   9100       return;
   9101     }
   9102   }
   9103 
   9104   TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
   9105   TailCallMode tail_call_mode =
   9106       function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
   9107 
   9108   PushArgumentsFromEnvironment(arguments_count);
   9109   HInvokeFunction* call =
   9110       New<HInvokeFunction>(function, known_function, arguments_count,
   9111                            syntactic_tail_call_mode, tail_call_mode);
   9112   Drop(1);  // Function
   9113   ast_context()->ReturnInstruction(call, expr->id());
   9114 }
   9115 
   9116 
   9117 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) {
   9118   DCHECK(expr->expression()->IsProperty());
   9119 
   9120   if (!expr->IsMonomorphic()) {
   9121     return false;
   9122   }
   9123   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   9124   if (function_map->instance_type() != JS_FUNCTION_TYPE ||
   9125       !expr->target()->shared()->HasBuiltinFunctionId()) {
   9126     return false;
   9127   }
   9128 
   9129   switch (expr->target()->shared()->builtin_function_id()) {
   9130     case kFunctionCall: {
   9131       if (expr->arguments()->length() == 0) return false;
   9132       BuildFunctionCall(expr);
   9133       return true;
   9134     }
   9135     case kFunctionApply: {
   9136       // For .apply, only the pattern f.apply(receiver, arguments)
   9137       // is supported.
   9138       if (!CanBeFunctionApplyArguments(expr)) return false;
   9139 
   9140       BuildFunctionApply(expr);
   9141       return true;
   9142     }
   9143     default: { return false; }
   9144   }
   9145   UNREACHABLE();
   9146 }
   9147 
   9148 
   9149 // f.apply(...)
   9150 void HOptimizedGraphBuilder::BuildFunctionApply(Call* expr) {
   9151   ZoneList<Expression*>* args = expr->arguments();
   9152   CHECK_ALIVE(VisitForValue(args->at(0)));
   9153   HValue* receiver = Pop();  // receiver
   9154   HValue* function = Pop();  // f
   9155   Drop(1);  // apply
   9156 
   9157   // Make sure the arguments object is live.
   9158   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
   9159   LookupAndMakeLive(arg_two->var());
   9160 
   9161   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   9162   HValue* checked_function = AddCheckMap(function, function_map);
   9163 
   9164   if (function_state()->outer() == NULL) {
   9165     TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
   9166     TailCallMode tail_call_mode =
   9167         function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
   9168 
   9169     HInstruction* elements = Add<HArgumentsElements>(false);
   9170     HInstruction* length = Add<HArgumentsLength>(elements);
   9171     HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function);
   9172     HInstruction* result = New<HApplyArguments>(
   9173         function, wrapped_receiver, length, elements, tail_call_mode);
   9174     ast_context()->ReturnInstruction(result, expr->id());
   9175   } else {
   9176     // We are inside inlined function and we know exactly what is inside
   9177     // arguments object. But we need to be able to materialize at deopt.
   9178     DCHECK_EQ(environment()->arguments_environment()->parameter_count(),
   9179               function_state()->entry()->arguments_object()->arguments_count());
   9180     HArgumentsObject* args = function_state()->entry()->arguments_object();
   9181     const ZoneList<HValue*>* arguments_values = args->arguments_values();
   9182     int arguments_count = arguments_values->length();
   9183     Push(function);
   9184     Push(BuildWrapReceiver(receiver, checked_function));
   9185     for (int i = 1; i < arguments_count; i++) {
   9186       Push(arguments_values->at(i));
   9187     }
   9188     HandleIndirectCall(expr, function, arguments_count);
   9189   }
   9190 }
   9191 
   9192 
   9193 // f.call(...)
   9194 void HOptimizedGraphBuilder::BuildFunctionCall(Call* expr) {
   9195   HValue* function = Top();  // f
   9196   Handle<Map> function_map = expr->GetReceiverTypes()->first();
   9197   HValue* checked_function = AddCheckMap(function, function_map);
   9198 
   9199   // f and call are on the stack in the unoptimized code
   9200   // during evaluation of the arguments.
   9201   CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9202 
   9203   int args_length = expr->arguments()->length();
   9204   int receiver_index = args_length - 1;
   9205   // Patch the receiver.
   9206   HValue* receiver = BuildWrapReceiver(
   9207       environment()->ExpressionStackAt(receiver_index), checked_function);
   9208   environment()->SetExpressionStackAt(receiver_index, receiver);
   9209 
   9210   // Call must not be on the stack from now on.
   9211   int call_index = args_length + 1;
   9212   environment()->RemoveExpressionStackAt(call_index);
   9213 
   9214   HandleIndirectCall(expr, function, args_length);
   9215 }
   9216 
   9217 
   9218 HValue* HOptimizedGraphBuilder::ImplicitReceiverFor(HValue* function,
   9219                                                     Handle<JSFunction> target) {
   9220   SharedFunctionInfo* shared = target->shared();
   9221   if (is_sloppy(shared->language_mode()) && !shared->native()) {
   9222     // Cannot embed a direct reference to the global proxy
   9223     // as is it dropped on deserialization.
   9224     CHECK(!isolate()->serializer_enabled());
   9225     Handle<JSObject> global_proxy(target->context()->global_proxy());
   9226     return Add<HConstant>(global_proxy);
   9227   }
   9228   return graph()->GetConstantUndefined();
   9229 }
   9230 
   9231 
   9232 HValue* HOptimizedGraphBuilder::BuildArrayIndexOf(HValue* receiver,
   9233                                                   HValue* search_element,
   9234                                                   ElementsKind kind,
   9235                                                   ArrayIndexOfMode mode) {
   9236   DCHECK(IsFastElementsKind(kind));
   9237 
   9238   NoObservableSideEffectsScope no_effects(this);
   9239 
   9240   HValue* elements = AddLoadElements(receiver);
   9241   HValue* length = AddLoadArrayLength(receiver, kind);
   9242 
   9243   HValue* initial;
   9244   HValue* terminating;
   9245   Token::Value token;
   9246   LoopBuilder::Direction direction;
   9247   if (mode == kFirstIndexOf) {
   9248     initial = graph()->GetConstant0();
   9249     terminating = length;
   9250     token = Token::LT;
   9251     direction = LoopBuilder::kPostIncrement;
   9252   } else {
   9253     DCHECK_EQ(kLastIndexOf, mode);
   9254     initial = length;
   9255     terminating = graph()->GetConstant0();
   9256     token = Token::GT;
   9257     direction = LoopBuilder::kPreDecrement;
   9258   }
   9259 
   9260   Push(graph()->GetConstantMinus1());
   9261   if (IsFastDoubleElementsKind(kind) || IsFastSmiElementsKind(kind)) {
   9262     // Make sure that we can actually compare numbers correctly below, see
   9263     // https://code.google.com/p/chromium/issues/detail?id=407946 for details.
   9264     search_element = AddUncasted<HForceRepresentation>(
   9265         search_element, IsFastSmiElementsKind(kind) ? Representation::Smi()
   9266                                                     : Representation::Double());
   9267 
   9268     LoopBuilder loop(this, context(), direction);
   9269     {
   9270       HValue* index = loop.BeginBody(initial, terminating, token);
   9271       HValue* element = AddUncasted<HLoadKeyed>(
   9272           elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9273       IfBuilder if_issame(this);
   9274       if_issame.If<HCompareNumericAndBranch>(element, search_element,
   9275                                              Token::EQ_STRICT);
   9276       if_issame.Then();
   9277       {
   9278         Drop(1);
   9279         Push(index);
   9280         loop.Break();
   9281       }
   9282       if_issame.End();
   9283     }
   9284     loop.EndBody();
   9285   } else {
   9286     IfBuilder if_isstring(this);
   9287     if_isstring.If<HIsStringAndBranch>(search_element);
   9288     if_isstring.Then();
   9289     {
   9290       LoopBuilder loop(this, context(), direction);
   9291       {
   9292         HValue* index = loop.BeginBody(initial, terminating, token);
   9293         HValue* element = AddUncasted<HLoadKeyed>(
   9294             elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9295         IfBuilder if_issame(this);
   9296         if_issame.If<HIsStringAndBranch>(element);
   9297         if_issame.AndIf<HStringCompareAndBranch>(
   9298             element, search_element, Token::EQ_STRICT);
   9299         if_issame.Then();
   9300         {
   9301           Drop(1);
   9302           Push(index);
   9303           loop.Break();
   9304         }
   9305         if_issame.End();
   9306       }
   9307       loop.EndBody();
   9308     }
   9309     if_isstring.Else();
   9310     {
   9311       IfBuilder if_isnumber(this);
   9312       if_isnumber.If<HIsSmiAndBranch>(search_element);
   9313       if_isnumber.OrIf<HCompareMap>(
   9314           search_element, isolate()->factory()->heap_number_map());
   9315       if_isnumber.Then();
   9316       {
   9317         HValue* search_number =
   9318             AddUncasted<HForceRepresentation>(search_element,
   9319                                               Representation::Double());
   9320         LoopBuilder loop(this, context(), direction);
   9321         {
   9322           HValue* index = loop.BeginBody(initial, terminating, token);
   9323           HValue* element = AddUncasted<HLoadKeyed>(
   9324               elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9325 
   9326           IfBuilder if_element_isnumber(this);
   9327           if_element_isnumber.If<HIsSmiAndBranch>(element);
   9328           if_element_isnumber.OrIf<HCompareMap>(
   9329               element, isolate()->factory()->heap_number_map());
   9330           if_element_isnumber.Then();
   9331           {
   9332             HValue* number =
   9333                 AddUncasted<HForceRepresentation>(element,
   9334                                                   Representation::Double());
   9335             IfBuilder if_issame(this);
   9336             if_issame.If<HCompareNumericAndBranch>(
   9337                 number, search_number, Token::EQ_STRICT);
   9338             if_issame.Then();
   9339             {
   9340               Drop(1);
   9341               Push(index);
   9342               loop.Break();
   9343             }
   9344             if_issame.End();
   9345           }
   9346           if_element_isnumber.End();
   9347         }
   9348         loop.EndBody();
   9349       }
   9350       if_isnumber.Else();
   9351       {
   9352         LoopBuilder loop(this, context(), direction);
   9353         {
   9354           HValue* index = loop.BeginBody(initial, terminating, token);
   9355           HValue* element = AddUncasted<HLoadKeyed>(
   9356               elements, index, nullptr, nullptr, kind, ALLOW_RETURN_HOLE);
   9357           IfBuilder if_issame(this);
   9358           if_issame.If<HCompareObjectEqAndBranch>(
   9359               element, search_element);
   9360           if_issame.Then();
   9361           {
   9362             Drop(1);
   9363             Push(index);
   9364             loop.Break();
   9365           }
   9366           if_issame.End();
   9367         }
   9368         loop.EndBody();
   9369       }
   9370       if_isnumber.End();
   9371     }
   9372     if_isstring.End();
   9373   }
   9374 
   9375   return Pop();
   9376 }
   9377 
   9378 template <class T>
   9379 bool HOptimizedGraphBuilder::TryHandleArrayCall(T* expr, HValue* function) {
   9380   if (!array_function().is_identical_to(expr->target())) {
   9381     return false;
   9382   }
   9383 
   9384   Handle<AllocationSite> site = expr->allocation_site();
   9385   if (site.is_null()) return false;
   9386 
   9387   Add<HCheckValue>(function, array_function());
   9388 
   9389   int arguments_count = expr->arguments()->length();
   9390   if (TryInlineArrayCall(expr, arguments_count, site)) return true;
   9391 
   9392   HInstruction* call = PreProcessCall(New<HCallNewArray>(
   9393       function, arguments_count + 1, site->GetElementsKind(), site));
   9394   if (expr->IsCall()) Drop(1);
   9395   ast_context()->ReturnInstruction(call, expr->id());
   9396 
   9397   return true;
   9398 }
   9399 
   9400 
   9401 bool HOptimizedGraphBuilder::CanBeFunctionApplyArguments(Call* expr) {
   9402   ZoneList<Expression*>* args = expr->arguments();
   9403   if (args->length() != 2) return false;
   9404   VariableProxy* arg_two = args->at(1)->AsVariableProxy();
   9405   if (arg_two == NULL || !arg_two->var()->IsStackAllocated()) return false;
   9406   HValue* arg_two_value = environment()->Lookup(arg_two->var());
   9407   if (!arg_two_value->CheckFlag(HValue::kIsArguments)) return false;
   9408   DCHECK_NOT_NULL(current_info()->scope()->arguments());
   9409   return true;
   9410 }
   9411 
   9412 
   9413 void HOptimizedGraphBuilder::VisitCall(Call* expr) {
   9414   DCHECK(!HasStackOverflow());
   9415   DCHECK(current_block() != NULL);
   9416   DCHECK(current_block()->HasPredecessor());
   9417   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   9418   Expression* callee = expr->expression();
   9419   int argument_count = expr->arguments()->length() + 1;  // Plus receiver.
   9420   HInstruction* call = NULL;
   9421 
   9422   TailCallMode syntactic_tail_call_mode = expr->tail_call_mode();
   9423   TailCallMode tail_call_mode =
   9424       function_state()->ComputeTailCallMode(syntactic_tail_call_mode);
   9425 
   9426   Property* prop = callee->AsProperty();
   9427   if (prop != NULL) {
   9428     CHECK_ALIVE(VisitForValue(prop->obj()));
   9429     HValue* receiver = Top();
   9430 
   9431     SmallMapList* maps;
   9432     ComputeReceiverTypes(expr, receiver, &maps, this);
   9433 
   9434     if (prop->key()->IsPropertyName() && maps->length() > 0) {
   9435       Handle<String> name = prop->key()->AsLiteral()->AsPropertyName();
   9436       PropertyAccessInfo info(this, LOAD, maps->first(), name);
   9437       if (!info.CanAccessAsMonomorphic(maps)) {
   9438         HandlePolymorphicCallNamed(expr, receiver, maps, name);
   9439         return;
   9440       }
   9441     }
   9442     HValue* key = NULL;
   9443     if (!prop->key()->IsPropertyName()) {
   9444       CHECK_ALIVE(VisitForValue(prop->key()));
   9445       key = Pop();
   9446     }
   9447 
   9448     CHECK_ALIVE(PushLoad(prop, receiver, key));
   9449     HValue* function = Pop();
   9450 
   9451     if (function->IsConstant() &&
   9452         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9453       // Push the function under the receiver.
   9454       environment()->SetExpressionStackAt(0, function);
   9455       Push(receiver);
   9456 
   9457       Handle<JSFunction> known_function = Handle<JSFunction>::cast(
   9458           HConstant::cast(function)->handle(isolate()));
   9459       expr->set_target(known_function);
   9460 
   9461       if (TryIndirectCall(expr)) return;
   9462       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9463 
   9464       Handle<Map> map = maps->length() == 1 ? maps->first() : Handle<Map>();
   9465       if (TryInlineBuiltinMethodCall(known_function, map, expr->id(),
   9466                                      expr->arguments()->length())) {
   9467         if (FLAG_trace_inlining) {
   9468           PrintF("Inlining builtin ");
   9469           known_function->ShortPrint();
   9470           PrintF("\n");
   9471         }
   9472         return;
   9473       }
   9474       if (TryInlineApiMethodCall(expr, receiver, maps)) return;
   9475 
   9476       // Wrap the receiver if necessary.
   9477       if (NeedsWrapping(maps->first(), known_function)) {
   9478         // Since HWrapReceiver currently cannot actually wrap numbers and
   9479         // strings, use the regular call builtin for method calls to wrap
   9480         // the receiver.
   9481         // TODO(verwaest): Support creation of value wrappers directly in
   9482         // HWrapReceiver.
   9483         call = NewCallFunction(
   9484             function, argument_count, syntactic_tail_call_mode,
   9485             ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode);
   9486       } else if (TryInlineCall(expr)) {
   9487         return;
   9488       } else {
   9489         call =
   9490             NewCallConstantFunction(known_function, argument_count,
   9491                                     syntactic_tail_call_mode, tail_call_mode);
   9492       }
   9493 
   9494     } else {
   9495       ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED;
   9496       if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) {
   9497         // We have to use EAGER deoptimization here because Deoptimizer::SOFT
   9498         // gets ignored by the always-opt flag, which leads to incorrect code.
   9499         Add<HDeoptimize>(
   9500             DeoptimizeReason::kInsufficientTypeFeedbackForCallWithArguments,
   9501             Deoptimizer::EAGER);
   9502         arguments_flag = ARGUMENTS_FAKED;
   9503       }
   9504 
   9505       // Push the function under the receiver.
   9506       environment()->SetExpressionStackAt(0, function);
   9507       Push(receiver);
   9508 
   9509       CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag));
   9510       call = NewCallFunction(function, argument_count, syntactic_tail_call_mode,
   9511                              ConvertReceiverMode::kNotNullOrUndefined,
   9512                              tail_call_mode);
   9513     }
   9514     PushArgumentsFromEnvironment(argument_count);
   9515 
   9516   } else {
   9517     if (expr->is_possibly_eval()) {
   9518       return Bailout(kPossibleDirectCallToEval);
   9519     }
   9520 
   9521     // The function is on the stack in the unoptimized code during
   9522     // evaluation of the arguments.
   9523     CHECK_ALIVE(VisitForValue(expr->expression()));
   9524     HValue* function = Top();
   9525     if (function->IsConstant() &&
   9526         HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9527       Handle<Object> constant = HConstant::cast(function)->handle(isolate());
   9528       Handle<JSFunction> target = Handle<JSFunction>::cast(constant);
   9529       expr->SetKnownGlobalTarget(target);
   9530     }
   9531 
   9532     // Placeholder for the receiver.
   9533     Push(graph()->GetConstantUndefined());
   9534     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9535 
   9536     if (expr->IsMonomorphic() &&
   9537         !IsClassConstructor(expr->target()->shared()->kind())) {
   9538       Add<HCheckValue>(function, expr->target());
   9539 
   9540       // Patch the global object on the stack by the expected receiver.
   9541       HValue* receiver = ImplicitReceiverFor(function, expr->target());
   9542       const int receiver_index = argument_count - 1;
   9543       environment()->SetExpressionStackAt(receiver_index, receiver);
   9544 
   9545       if (TryInlineBuiltinFunctionCall(expr)) {
   9546         if (FLAG_trace_inlining) {
   9547           PrintF("Inlining builtin ");
   9548           expr->target()->ShortPrint();
   9549           PrintF("\n");
   9550         }
   9551         return;
   9552       }
   9553       if (TryInlineApiFunctionCall(expr, receiver)) return;
   9554       if (TryHandleArrayCall(expr, function)) return;
   9555       if (TryInlineCall(expr)) return;
   9556 
   9557       PushArgumentsFromEnvironment(argument_count);
   9558       call = NewCallConstantFunction(expr->target(), argument_count,
   9559                                      syntactic_tail_call_mode, tail_call_mode);
   9560     } else {
   9561       PushArgumentsFromEnvironment(argument_count);
   9562       if (expr->is_uninitialized()) {
   9563         // We've never seen this call before, so let's have Crankshaft learn
   9564         // through the type vector.
   9565         call = NewCallFunctionViaIC(function, argument_count,
   9566                                     syntactic_tail_call_mode,
   9567                                     ConvertReceiverMode::kNullOrUndefined,
   9568                                     tail_call_mode, expr->CallFeedbackICSlot());
   9569       } else {
   9570         call = NewCallFunction(
   9571             function, argument_count, syntactic_tail_call_mode,
   9572             ConvertReceiverMode::kNullOrUndefined, tail_call_mode);
   9573       }
   9574     }
   9575   }
   9576 
   9577   Drop(1);  // Drop the function.
   9578   return ast_context()->ReturnInstruction(call, expr->id());
   9579 }
   9580 
   9581 bool HOptimizedGraphBuilder::TryInlineArrayCall(Expression* expression,
   9582                                                 int argument_count,
   9583                                                 Handle<AllocationSite> site) {
   9584   Handle<JSFunction> caller = current_info()->closure();
   9585   Handle<JSFunction> target = array_function();
   9586 
   9587   if (!site->CanInlineCall()) {
   9588     TraceInline(target, caller, "AllocationSite requested no inlining.");
   9589     return false;
   9590   }
   9591 
   9592   if (argument_count > 1) {
   9593     TraceInline(target, caller, "Too many arguments to inline.");
   9594     return false;
   9595   }
   9596 
   9597   int array_length = 0;
   9598   // Do not inline if the constant length argument is not a smi or outside the
   9599   // valid range for unrolled loop initialization.
   9600   if (argument_count == 1) {
   9601     HValue* argument = Top();
   9602     if (!argument->IsConstant()) {
   9603       TraceInline(target, caller,
   9604                   "Dont inline [new] Array(n) where n isn't constant.");
   9605       return false;
   9606     }
   9607 
   9608     HConstant* constant_argument = HConstant::cast(argument);
   9609     if (!constant_argument->HasSmiValue()) {
   9610       TraceInline(target, caller,
   9611                   "Constant length outside of valid inlining range.");
   9612       return false;
   9613     }
   9614     array_length = constant_argument->Integer32Value();
   9615     if (array_length < 0 || array_length > kElementLoopUnrollThreshold) {
   9616       TraceInline(target, caller,
   9617                   "Constant length outside of valid inlining range.");
   9618       return false;
   9619     }
   9620   }
   9621 
   9622   TraceInline(target, caller, NULL);
   9623 
   9624   NoObservableSideEffectsScope no_effects(this);
   9625 
   9626   // Register on the site for deoptimization if the transition feedback changes.
   9627   top_info()->dependencies()->AssumeTransitionStable(site);
   9628 
   9629   // Build the array.
   9630   ElementsKind kind = site->GetElementsKind();
   9631   HValue* capacity;
   9632   HValue* length;
   9633   if (array_length == 0) {
   9634     STATIC_ASSERT(0 < JSArray::kPreallocatedArrayElements);
   9635     const int initial_capacity = JSArray::kPreallocatedArrayElements;
   9636     capacity = Add<HConstant>(initial_capacity);
   9637     length = graph()->GetConstant0();
   9638   } else {
   9639     length = Top();
   9640     capacity = length;
   9641     kind = GetHoleyElementsKind(kind);
   9642   }
   9643 
   9644   // These HForceRepresentations are because we store these as fields in the
   9645   // objects we construct, and an int32-to-smi HChange could deopt. Accept
   9646   // the deopt possibility now, before allocation occurs.
   9647   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   9648   capacity = AddUncasted<HForceRepresentation>(capacity, Representation::Smi());
   9649 
   9650   // Generate size calculation code here in order to make it dominate
   9651   // the JSArray allocation.
   9652   HValue* elements_size = BuildCalculateElementsSize(kind, capacity);
   9653 
   9654   // Bail out for large objects.
   9655   HValue* max_size = Add<HConstant>(kMaxRegularHeapObjectSize);
   9656   Add<HBoundsCheck>(elements_size, max_size);
   9657 
   9658   // Allocate (dealing with failure appropriately).
   9659   AllocationSiteMode mode = DONT_TRACK_ALLOCATION_SITE;
   9660   HAllocate* new_object = AllocateJSArrayObject(mode);
   9661 
   9662   // Fill in the fields: map, properties, length.
   9663   Handle<Map> map_constant(isolate()->get_initial_js_array_map(kind));
   9664   HValue* map = Add<HConstant>(map_constant);
   9665 
   9666   BuildJSArrayHeader(new_object, map,
   9667                      nullptr,  // set elements to empty fixed array
   9668                      mode, kind, nullptr, length);
   9669 
   9670   // Allocate and initialize the elements.
   9671   HAllocate* elements = BuildAllocateElements(kind, elements_size);
   9672   BuildInitializeElementsHeader(elements, kind, capacity);
   9673   BuildFillElementsWithHole(elements, kind, graph()->GetConstant0(), capacity);
   9674 
   9675   // Set the elements.
   9676   Add<HStoreNamedField>(new_object, HObjectAccess::ForElementsPointer(),
   9677                         elements);
   9678 
   9679   int args_to_drop = argument_count + (expression->IsCall() ? 2 : 1);
   9680   Drop(args_to_drop);
   9681   ast_context()->ReturnValue(new_object);
   9682   return true;
   9683 }
   9684 
   9685 
   9686 // Checks whether allocation using the given constructor can be inlined.
   9687 static bool IsAllocationInlineable(Handle<JSFunction> constructor) {
   9688   return constructor->has_initial_map() &&
   9689          !IsSubclassConstructor(constructor->shared()->kind()) &&
   9690          constructor->initial_map()->instance_type() == JS_OBJECT_TYPE &&
   9691          constructor->initial_map()->instance_size() <
   9692              HAllocate::kMaxInlineSize;
   9693 }
   9694 
   9695 void HOptimizedGraphBuilder::VisitCallNew(CallNew* expr) {
   9696   DCHECK(!HasStackOverflow());
   9697   DCHECK(current_block() != NULL);
   9698   DCHECK(current_block()->HasPredecessor());
   9699   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   9700   int argument_count = expr->arguments()->length() + 1;  // Plus constructor.
   9701   Factory* factory = isolate()->factory();
   9702 
   9703   // The constructor function is on the stack in the unoptimized code
   9704   // during evaluation of the arguments.
   9705   CHECK_ALIVE(VisitForValue(expr->expression()));
   9706   HValue* function = Top();
   9707   CHECK_ALIVE(VisitExpressions(expr->arguments()));
   9708 
   9709   if (function->IsConstant() &&
   9710       HConstant::cast(function)->handle(isolate())->IsJSFunction()) {
   9711     Handle<Object> constant = HConstant::cast(function)->handle(isolate());
   9712     expr->SetKnownGlobalTarget(Handle<JSFunction>::cast(constant));
   9713   }
   9714 
   9715   if (FLAG_inline_construct &&
   9716       expr->IsMonomorphic() &&
   9717       IsAllocationInlineable(expr->target())) {
   9718     Handle<JSFunction> constructor = expr->target();
   9719     DCHECK(
   9720         constructor->shared()->construct_stub() ==
   9721             isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric) ||
   9722         constructor->shared()->construct_stub() ==
   9723             isolate()->builtins()->builtin(Builtins::kJSConstructStubApi));
   9724     HValue* check = Add<HCheckValue>(function, constructor);
   9725 
   9726     // Force completion of inobject slack tracking before generating
   9727     // allocation code to finalize instance size.
   9728     constructor->CompleteInobjectSlackTrackingIfActive();
   9729 
   9730     // Calculate instance size from initial map of constructor.
   9731     DCHECK(constructor->has_initial_map());
   9732     Handle<Map> initial_map(constructor->initial_map());
   9733     int instance_size = initial_map->instance_size();
   9734 
   9735     // Allocate an instance of the implicit receiver object.
   9736     HValue* size_in_bytes = Add<HConstant>(instance_size);
   9737     HAllocationMode allocation_mode;
   9738     HAllocate* receiver = BuildAllocate(
   9739         size_in_bytes, HType::JSObject(), JS_OBJECT_TYPE, allocation_mode);
   9740     receiver->set_known_initial_map(initial_map);
   9741 
   9742     // Initialize map and fields of the newly allocated object.
   9743     { NoObservableSideEffectsScope no_effects(this);
   9744       DCHECK(initial_map->instance_type() == JS_OBJECT_TYPE);
   9745       Add<HStoreNamedField>(receiver,
   9746           HObjectAccess::ForMapAndOffset(initial_map, JSObject::kMapOffset),
   9747           Add<HConstant>(initial_map));
   9748       HValue* empty_fixed_array = Add<HConstant>(factory->empty_fixed_array());
   9749       Add<HStoreNamedField>(receiver,
   9750           HObjectAccess::ForMapAndOffset(initial_map,
   9751                                          JSObject::kPropertiesOffset),
   9752           empty_fixed_array);
   9753       Add<HStoreNamedField>(receiver,
   9754           HObjectAccess::ForMapAndOffset(initial_map,
   9755                                          JSObject::kElementsOffset),
   9756           empty_fixed_array);
   9757       BuildInitializeInobjectProperties(receiver, initial_map);
   9758     }
   9759 
   9760     // Replace the constructor function with a newly allocated receiver using
   9761     // the index of the receiver from the top of the expression stack.
   9762     const int receiver_index = argument_count - 1;
   9763     DCHECK(environment()->ExpressionStackAt(receiver_index) == function);
   9764     environment()->SetExpressionStackAt(receiver_index, receiver);
   9765 
   9766     if (TryInlineConstruct(expr, receiver)) {
   9767       // Inlining worked, add a dependency on the initial map to make sure that
   9768       // this code is deoptimized whenever the initial map of the constructor
   9769       // changes.
   9770       top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
   9771       return;
   9772     }
   9773 
   9774     // TODO(mstarzinger): For now we remove the previous HAllocate and all
   9775     // corresponding instructions and instead add HPushArguments for the
   9776     // arguments in case inlining failed.  What we actually should do is for
   9777     // inlining to try to build a subgraph without mutating the parent graph.
   9778     HInstruction* instr = current_block()->last();
   9779     do {
   9780       HInstruction* prev_instr = instr->previous();
   9781       instr->DeleteAndReplaceWith(NULL);
   9782       instr = prev_instr;
   9783     } while (instr != check);
   9784     environment()->SetExpressionStackAt(receiver_index, function);
   9785   } else {
   9786     // The constructor function is both an operand to the instruction and an
   9787     // argument to the construct call.
   9788     if (TryHandleArrayCall(expr, function)) return;
   9789   }
   9790 
   9791   HValue* arity = Add<HConstant>(argument_count - 1);
   9792   HValue* op_vals[] = {function, function, arity};
   9793   Callable callable = CodeFactory::Construct(isolate());
   9794   HConstant* stub = Add<HConstant>(callable.code());
   9795   PushArgumentsFromEnvironment(argument_count);
   9796   HInstruction* construct = New<HCallWithDescriptor>(
   9797       stub, argument_count, callable.descriptor(), ArrayVector(op_vals));
   9798   return ast_context()->ReturnInstruction(construct, expr->id());
   9799 }
   9800 
   9801 
   9802 void HOptimizedGraphBuilder::BuildInitializeInobjectProperties(
   9803     HValue* receiver, Handle<Map> initial_map) {
   9804   if (initial_map->GetInObjectProperties() != 0) {
   9805     HConstant* undefined = graph()->GetConstantUndefined();
   9806     for (int i = 0; i < initial_map->GetInObjectProperties(); i++) {
   9807       int property_offset = initial_map->GetInObjectPropertyOffset(i);
   9808       Add<HStoreNamedField>(receiver, HObjectAccess::ForMapAndOffset(
   9809                                           initial_map, property_offset),
   9810                             undefined);
   9811     }
   9812   }
   9813 }
   9814 
   9815 
   9816 HValue* HGraphBuilder::BuildAllocateEmptyArrayBuffer(HValue* byte_length) {
   9817   // We HForceRepresentation here to avoid allocations during an *-to-tagged
   9818   // HChange that could cause GC while the array buffer object is not fully
   9819   // initialized.
   9820   HObjectAccess byte_length_access(HObjectAccess::ForJSArrayBufferByteLength());
   9821   byte_length = AddUncasted<HForceRepresentation>(
   9822       byte_length, byte_length_access.representation());
   9823   HAllocate* result =
   9824       BuildAllocate(Add<HConstant>(JSArrayBuffer::kSizeWithInternalFields),
   9825                     HType::JSObject(), JS_ARRAY_BUFFER_TYPE, HAllocationMode());
   9826 
   9827   HValue* native_context = BuildGetNativeContext();
   9828   Add<HStoreNamedField>(
   9829       result, HObjectAccess::ForMap(),
   9830       Add<HLoadNamedField>(
   9831           native_context, nullptr,
   9832           HObjectAccess::ForContextSlot(Context::ARRAY_BUFFER_MAP_INDEX)));
   9833 
   9834   HConstant* empty_fixed_array =
   9835       Add<HConstant>(isolate()->factory()->empty_fixed_array());
   9836   Add<HStoreNamedField>(
   9837       result, HObjectAccess::ForJSArrayOffset(JSArray::kPropertiesOffset),
   9838       empty_fixed_array);
   9839   Add<HStoreNamedField>(
   9840       result, HObjectAccess::ForJSArrayOffset(JSArray::kElementsOffset),
   9841       empty_fixed_array);
   9842   Add<HStoreNamedField>(
   9843       result, HObjectAccess::ForJSArrayBufferBackingStore().WithRepresentation(
   9844                   Representation::Smi()),
   9845       graph()->GetConstant0());
   9846   Add<HStoreNamedField>(result, byte_length_access, byte_length);
   9847   Add<HStoreNamedField>(result, HObjectAccess::ForJSArrayBufferBitFieldSlot(),
   9848                         graph()->GetConstant0());
   9849   Add<HStoreNamedField>(
   9850       result, HObjectAccess::ForJSArrayBufferBitField(),
   9851       Add<HConstant>((1 << JSArrayBuffer::IsExternal::kShift) |
   9852                      (1 << JSArrayBuffer::IsNeuterable::kShift)));
   9853 
   9854   for (int field = 0; field < v8::ArrayBuffer::kInternalFieldCount; ++field) {
   9855     Add<HStoreNamedField>(
   9856         result,
   9857         HObjectAccess::ForObservableJSObjectOffset(
   9858             JSArrayBuffer::kSize + field * kPointerSize, Representation::Smi()),
   9859         graph()->GetConstant0());
   9860   }
   9861 
   9862   return result;
   9863 }
   9864 
   9865 
   9866 template <class ViewClass>
   9867 void HGraphBuilder::BuildArrayBufferViewInitialization(
   9868     HValue* obj,
   9869     HValue* buffer,
   9870     HValue* byte_offset,
   9871     HValue* byte_length) {
   9872 
   9873   for (int offset = ViewClass::kSize;
   9874        offset < ViewClass::kSizeWithInternalFields;
   9875        offset += kPointerSize) {
   9876     Add<HStoreNamedField>(obj,
   9877         HObjectAccess::ForObservableJSObjectOffset(offset),
   9878         graph()->GetConstant0());
   9879   }
   9880 
   9881   Add<HStoreNamedField>(
   9882       obj,
   9883       HObjectAccess::ForJSArrayBufferViewByteOffset(),
   9884       byte_offset);
   9885   Add<HStoreNamedField>(
   9886       obj,
   9887       HObjectAccess::ForJSArrayBufferViewByteLength(),
   9888       byte_length);
   9889   Add<HStoreNamedField>(obj, HObjectAccess::ForJSArrayBufferViewBuffer(),
   9890                         buffer);
   9891 }
   9892 
   9893 
   9894 HValue* HOptimizedGraphBuilder::BuildAllocateExternalElements(
   9895     ExternalArrayType array_type,
   9896     bool is_zero_byte_offset,
   9897     HValue* buffer, HValue* byte_offset, HValue* length) {
   9898   Handle<Map> external_array_map(
   9899       isolate()->heap()->MapForFixedTypedArray(array_type));
   9900 
   9901   // The HForceRepresentation is to prevent possible deopt on int-smi
   9902   // conversion after allocation but before the new object fields are set.
   9903   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   9904   HValue* elements = Add<HAllocate>(
   9905       Add<HConstant>(FixedTypedArrayBase::kHeaderSize), HType::HeapObject(),
   9906       NOT_TENURED, external_array_map->instance_type(),
   9907       graph()->GetConstant0());
   9908 
   9909   AddStoreMapConstant(elements, external_array_map);
   9910   Add<HStoreNamedField>(elements,
   9911       HObjectAccess::ForFixedArrayLength(), length);
   9912 
   9913   HValue* backing_store = Add<HLoadNamedField>(
   9914       buffer, nullptr, HObjectAccess::ForJSArrayBufferBackingStore());
   9915 
   9916   HValue* typed_array_start;
   9917   if (is_zero_byte_offset) {
   9918     typed_array_start = backing_store;
   9919   } else {
   9920     HInstruction* external_pointer =
   9921         AddUncasted<HAdd>(backing_store, byte_offset);
   9922     // Arguments are checked prior to call to TypedArrayInitialize,
   9923     // including byte_offset.
   9924     external_pointer->ClearFlag(HValue::kCanOverflow);
   9925     typed_array_start = external_pointer;
   9926   }
   9927 
   9928   Add<HStoreNamedField>(elements,
   9929                         HObjectAccess::ForFixedTypedArrayBaseBasePointer(),
   9930                         graph()->GetConstant0());
   9931   Add<HStoreNamedField>(elements,
   9932                         HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
   9933                         typed_array_start);
   9934 
   9935   return elements;
   9936 }
   9937 
   9938 
   9939 HValue* HOptimizedGraphBuilder::BuildAllocateFixedTypedArray(
   9940     ExternalArrayType array_type, size_t element_size,
   9941     ElementsKind fixed_elements_kind, HValue* byte_length, HValue* length,
   9942     bool initialize) {
   9943   STATIC_ASSERT(
   9944       (FixedTypedArrayBase::kHeaderSize & kObjectAlignmentMask) == 0);
   9945   HValue* total_size;
   9946 
   9947   // if fixed array's elements are not aligned to object's alignment,
   9948   // we need to align the whole array to object alignment.
   9949   if (element_size % kObjectAlignment != 0) {
   9950     total_size = BuildObjectSizeAlignment(
   9951         byte_length, FixedTypedArrayBase::kHeaderSize);
   9952   } else {
   9953     total_size = AddUncasted<HAdd>(byte_length,
   9954         Add<HConstant>(FixedTypedArrayBase::kHeaderSize));
   9955     total_size->ClearFlag(HValue::kCanOverflow);
   9956   }
   9957 
   9958   // The HForceRepresentation is to prevent possible deopt on int-smi
   9959   // conversion after allocation but before the new object fields are set.
   9960   length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   9961   Handle<Map> fixed_typed_array_map(
   9962       isolate()->heap()->MapForFixedTypedArray(array_type));
   9963   HAllocate* elements = Add<HAllocate>(
   9964       total_size, HType::HeapObject(), NOT_TENURED,
   9965       fixed_typed_array_map->instance_type(), graph()->GetConstant0());
   9966 
   9967 #ifndef V8_HOST_ARCH_64_BIT
   9968   if (array_type == kExternalFloat64Array) {
   9969     elements->MakeDoubleAligned();
   9970   }
   9971 #endif
   9972 
   9973   AddStoreMapConstant(elements, fixed_typed_array_map);
   9974 
   9975   Add<HStoreNamedField>(elements,
   9976       HObjectAccess::ForFixedArrayLength(),
   9977       length);
   9978   Add<HStoreNamedField>(
   9979       elements, HObjectAccess::ForFixedTypedArrayBaseBasePointer(), elements);
   9980 
   9981   Add<HStoreNamedField>(
   9982       elements, HObjectAccess::ForFixedTypedArrayBaseExternalPointer(),
   9983       Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()));
   9984 
   9985   HValue* filler = Add<HConstant>(static_cast<int32_t>(0));
   9986 
   9987   if (initialize) {
   9988     LoopBuilder builder(this, context(), LoopBuilder::kPostIncrement);
   9989 
   9990     HValue* backing_store = AddUncasted<HAdd>(
   9991         Add<HConstant>(ExternalReference::fixed_typed_array_base_data_offset()),
   9992         elements, AddOfExternalAndTagged);
   9993 
   9994     HValue* key = builder.BeginBody(
   9995         Add<HConstant>(static_cast<int32_t>(0)),
   9996         length, Token::LT);
   9997     Add<HStoreKeyed>(backing_store, key, filler, elements, fixed_elements_kind);
   9998 
   9999     builder.EndBody();
   10000   }
   10001   return elements;
   10002 }
   10003 
   10004 
   10005 void HOptimizedGraphBuilder::GenerateTypedArrayInitialize(
   10006     CallRuntime* expr) {
   10007   ZoneList<Expression*>* arguments = expr->arguments();
   10008 
   10009   static const int kObjectArg = 0;
   10010   static const int kArrayIdArg = 1;
   10011   static const int kBufferArg = 2;
   10012   static const int kByteOffsetArg = 3;
   10013   static const int kByteLengthArg = 4;
   10014   static const int kInitializeArg = 5;
   10015   static const int kArgsLength = 6;
   10016   DCHECK(arguments->length() == kArgsLength);
   10017 
   10018 
   10019   CHECK_ALIVE(VisitForValue(arguments->at(kObjectArg)));
   10020   HValue* obj = Pop();
   10021 
   10022   if (!arguments->at(kArrayIdArg)->IsLiteral()) {
   10023     // This should never happen in real use, but can happen when fuzzing.
   10024     // Just bail out.
   10025     Bailout(kNeedSmiLiteral);
   10026     return;
   10027   }
   10028   Handle<Object> value =
   10029       static_cast<Literal*>(arguments->at(kArrayIdArg))->value();
   10030   if (!value->IsSmi()) {
   10031     // This should never happen in real use, but can happen when fuzzing.
   10032     // Just bail out.
   10033     Bailout(kNeedSmiLiteral);
   10034     return;
   10035   }
   10036   int array_id = Smi::cast(*value)->value();
   10037 
   10038   HValue* buffer;
   10039   if (!arguments->at(kBufferArg)->IsNullLiteral()) {
   10040     CHECK_ALIVE(VisitForValue(arguments->at(kBufferArg)));
   10041     buffer = Pop();
   10042   } else {
   10043     buffer = NULL;
   10044   }
   10045 
   10046   HValue* byte_offset;
   10047   bool is_zero_byte_offset;
   10048 
   10049   if (arguments->at(kByteOffsetArg)->IsLiteral() &&
   10050       Smi::kZero ==
   10051           *static_cast<Literal*>(arguments->at(kByteOffsetArg))->value()) {
   10052     byte_offset = Add<HConstant>(static_cast<int32_t>(0));
   10053     is_zero_byte_offset = true;
   10054   } else {
   10055     CHECK_ALIVE(VisitForValue(arguments->at(kByteOffsetArg)));
   10056     byte_offset = Pop();
   10057     is_zero_byte_offset = false;
   10058     DCHECK(buffer != NULL);
   10059   }
   10060 
   10061   CHECK_ALIVE(VisitForValue(arguments->at(kByteLengthArg)));
   10062   HValue* byte_length = Pop();
   10063 
   10064   CHECK(arguments->at(kInitializeArg)->IsLiteral());
   10065   bool initialize = static_cast<Literal*>(arguments->at(kInitializeArg))
   10066                         ->value()
   10067                         ->BooleanValue();
   10068 
   10069   NoObservableSideEffectsScope scope(this);
   10070   IfBuilder byte_offset_smi(this);
   10071 
   10072   if (!is_zero_byte_offset) {
   10073     byte_offset_smi.If<HIsSmiAndBranch>(byte_offset);
   10074     byte_offset_smi.Then();
   10075   }
   10076 
   10077   ExternalArrayType array_type =
   10078       kExternalInt8Array;  // Bogus initialization.
   10079   size_t element_size = 1;  // Bogus initialization.
   10080   ElementsKind fixed_elements_kind =  // Bogus initialization.
   10081       INT8_ELEMENTS;
   10082   Runtime::ArrayIdToTypeAndSize(array_id,
   10083       &array_type,
   10084       &fixed_elements_kind,
   10085       &element_size);
   10086 
   10087 
   10088   { //  byte_offset is Smi.
   10089     HValue* allocated_buffer = buffer;
   10090     if (buffer == NULL) {
   10091       allocated_buffer = BuildAllocateEmptyArrayBuffer(byte_length);
   10092     }
   10093     BuildArrayBufferViewInitialization<JSTypedArray>(obj, allocated_buffer,
   10094                                                      byte_offset, byte_length);
   10095 
   10096 
   10097     HInstruction* length = AddUncasted<HDiv>(byte_length,
   10098         Add<HConstant>(static_cast<int32_t>(element_size)));
   10099     // Callers (in typedarray.js) ensure that length <= %_MaxSmi().
   10100     length = AddUncasted<HForceRepresentation>(length, Representation::Smi());
   10101 
   10102     Add<HStoreNamedField>(obj,
   10103         HObjectAccess::ForJSTypedArrayLength(),
   10104         length);
   10105 
   10106     HValue* elements;
   10107     if (buffer != NULL) {
   10108       elements = BuildAllocateExternalElements(
   10109           array_type, is_zero_byte_offset, buffer, byte_offset, length);
   10110     } else {
   10111       DCHECK(is_zero_byte_offset);
   10112       elements = BuildAllocateFixedTypedArray(array_type, element_size,
   10113                                               fixed_elements_kind, byte_length,
   10114                                               length, initialize);
   10115     }
   10116     Add<HStoreNamedField>(
   10117         obj, HObjectAccess::ForElementsPointer(), elements);
   10118   }
   10119 
   10120   if (!is_zero_byte_offset) {
   10121     byte_offset_smi.Else();
   10122     { //  byte_offset is not Smi.
   10123       Push(obj);
   10124       CHECK_ALIVE(VisitForValue(arguments->at(kArrayIdArg)));
   10125       Push(buffer);
   10126       Push(byte_offset);
   10127       Push(byte_length);
   10128       CHECK_ALIVE(VisitForValue(arguments->at(kInitializeArg)));
   10129       PushArgumentsFromEnvironment(kArgsLength);
   10130       Add<HCallRuntime>(expr->function(), kArgsLength);
   10131     }
   10132   }
   10133   byte_offset_smi.End();
   10134 }
   10135 
   10136 
   10137 void HOptimizedGraphBuilder::GenerateMaxSmi(CallRuntime* expr) {
   10138   DCHECK(expr->arguments()->length() == 0);
   10139   HConstant* max_smi = New<HConstant>(static_cast<int32_t>(Smi::kMaxValue));
   10140   return ast_context()->ReturnInstruction(max_smi, expr->id());
   10141 }
   10142 
   10143 
   10144 void HOptimizedGraphBuilder::GenerateTypedArrayMaxSizeInHeap(
   10145     CallRuntime* expr) {
   10146   DCHECK(expr->arguments()->length() == 0);
   10147   HConstant* result = New<HConstant>(static_cast<int32_t>(
   10148         FLAG_typed_array_max_size_in_heap));
   10149   return ast_context()->ReturnInstruction(result, expr->id());
   10150 }
   10151 
   10152 
   10153 void HOptimizedGraphBuilder::GenerateArrayBufferGetByteLength(
   10154     CallRuntime* expr) {
   10155   DCHECK(expr->arguments()->length() == 1);
   10156   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10157   HValue* buffer = Pop();
   10158   HInstruction* result = New<HLoadNamedField>(
   10159       buffer, nullptr, HObjectAccess::ForJSArrayBufferByteLength());
   10160   return ast_context()->ReturnInstruction(result, expr->id());
   10161 }
   10162 
   10163 
   10164 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteLength(
   10165     CallRuntime* expr) {
   10166   NoObservableSideEffectsScope scope(this);
   10167   DCHECK(expr->arguments()->length() == 1);
   10168   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10169   HValue* view = Pop();
   10170 
   10171   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
   10172       view, nullptr,
   10173       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteLengthOffset)));
   10174 }
   10175 
   10176 
   10177 void HOptimizedGraphBuilder::GenerateArrayBufferViewGetByteOffset(
   10178     CallRuntime* expr) {
   10179   NoObservableSideEffectsScope scope(this);
   10180   DCHECK(expr->arguments()->length() == 1);
   10181   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10182   HValue* view = Pop();
   10183 
   10184   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
   10185       view, nullptr,
   10186       FieldIndex::ForInObjectOffset(JSArrayBufferView::kByteOffsetOffset)));
   10187 }
   10188 
   10189 
   10190 void HOptimizedGraphBuilder::GenerateTypedArrayGetLength(
   10191     CallRuntime* expr) {
   10192   NoObservableSideEffectsScope scope(this);
   10193   DCHECK(expr->arguments()->length() == 1);
   10194   CHECK_ALIVE(VisitForValue(expr->arguments()->at(0)));
   10195   HValue* view = Pop();
   10196 
   10197   return ast_context()->ReturnValue(BuildArrayBufferViewFieldAccessor(
   10198       view, nullptr,
   10199       FieldIndex::ForInObjectOffset(JSTypedArray::kLengthOffset)));
   10200 }
   10201 
   10202 
   10203 void HOptimizedGraphBuilder::VisitCallRuntime(CallRuntime* expr) {
   10204   DCHECK(!HasStackOverflow());
   10205   DCHECK(current_block() != NULL);
   10206   DCHECK(current_block()->HasPredecessor());
   10207   if (expr->is_jsruntime()) {
   10208     // Crankshaft always specializes to the native context, so we can just grab
   10209     // the constant function from the current native context and embed that into
   10210     // the code object.
   10211     Handle<JSFunction> known_function(
   10212         JSFunction::cast(
   10213             current_info()->native_context()->get(expr->context_index())),
   10214         isolate());
   10215 
   10216     // The callee and the receiver both have to be pushed onto the operand stack
   10217     // before arguments are being evaluated.
   10218     HConstant* function = Add<HConstant>(known_function);
   10219     HValue* receiver = ImplicitReceiverFor(function, known_function);
   10220     Push(function);
   10221     Push(receiver);
   10222 
   10223     int argument_count = expr->arguments()->length() + 1;  // Count receiver.
   10224     CHECK_ALIVE(VisitExpressions(expr->arguments()));
   10225     PushArgumentsFromEnvironment(argument_count);
   10226     HInstruction* call = NewCallConstantFunction(known_function, argument_count,
   10227                                                  TailCallMode::kDisallow,
   10228                                                  TailCallMode::kDisallow);
   10229     Drop(1);  // Function
   10230     return ast_context()->ReturnInstruction(call, expr->id());
   10231   }
   10232 
   10233   const Runtime::Function* function = expr->function();
   10234   DCHECK(function != NULL);
   10235   switch (function->function_id) {
   10236 #define CALL_INTRINSIC_GENERATOR(Name) \
   10237   case Runtime::kInline##Name:         \
   10238     return Generate##Name(expr);
   10239 
   10240     FOR_EACH_HYDROGEN_INTRINSIC(CALL_INTRINSIC_GENERATOR)
   10241 #undef CALL_INTRINSIC_GENERATOR
   10242     default: {
   10243       int argument_count = expr->arguments()->length();
   10244       CHECK_ALIVE(VisitExpressions(expr->arguments()));
   10245       PushArgumentsFromEnvironment(argument_count);
   10246       HCallRuntime* call = New<HCallRuntime>(function, argument_count);
   10247       return ast_context()->ReturnInstruction(call, expr->id());
   10248     }
   10249   }
   10250 }
   10251 
   10252 
   10253 void HOptimizedGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
   10254   DCHECK(!HasStackOverflow());
   10255   DCHECK(current_block() != NULL);
   10256   DCHECK(current_block()->HasPredecessor());
   10257   switch (expr->op()) {
   10258     case Token::DELETE: return VisitDelete(expr);
   10259     case Token::VOID: return VisitVoid(expr);
   10260     case Token::TYPEOF: return VisitTypeof(expr);
   10261     case Token::NOT: return VisitNot(expr);
   10262     default: UNREACHABLE();
   10263   }
   10264 }
   10265 
   10266 
   10267 void HOptimizedGraphBuilder::VisitDelete(UnaryOperation* expr) {
   10268   Property* prop = expr->expression()->AsProperty();
   10269   VariableProxy* proxy = expr->expression()->AsVariableProxy();
   10270   if (prop != NULL) {
   10271     CHECK_ALIVE(VisitForValue(prop->obj()));
   10272     CHECK_ALIVE(VisitForValue(prop->key()));
   10273     HValue* key = Pop();
   10274     HValue* obj = Pop();
   10275     Add<HPushArguments>(obj, key);
   10276     HInstruction* instr = New<HCallRuntime>(
   10277         Runtime::FunctionForId(is_strict(function_language_mode())
   10278                                    ? Runtime::kDeleteProperty_Strict
   10279                                    : Runtime::kDeleteProperty_Sloppy),
   10280         2);
   10281     return ast_context()->ReturnInstruction(instr, expr->id());
   10282   } else if (proxy != NULL) {
   10283     Variable* var = proxy->var();
   10284     if (var->IsUnallocated()) {
   10285       Bailout(kDeleteWithGlobalVariable);
   10286     } else if (var->IsStackAllocated() || var->IsContextSlot()) {
   10287       // Result of deleting non-global variables is false.  'this' is not really
   10288       // a variable, though we implement it as one.  The subexpression does not
   10289       // have side effects.
   10290       HValue* value = var->is_this() ? graph()->GetConstantTrue()
   10291                                      : graph()->GetConstantFalse();
   10292       return ast_context()->ReturnValue(value);
   10293     } else {
   10294       Bailout(kDeleteWithNonGlobalVariable);
   10295     }
   10296   } else {
   10297     // Result of deleting non-property, non-variable reference is true.
   10298     // Evaluate the subexpression for side effects.
   10299     CHECK_ALIVE(VisitForEffect(expr->expression()));
   10300     return ast_context()->ReturnValue(graph()->GetConstantTrue());
   10301   }
   10302 }
   10303 
   10304 
   10305 void HOptimizedGraphBuilder::VisitVoid(UnaryOperation* expr) {
   10306   CHECK_ALIVE(VisitForEffect(expr->expression()));
   10307   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   10308 }
   10309 
   10310 
   10311 void HOptimizedGraphBuilder::VisitTypeof(UnaryOperation* expr) {
   10312   CHECK_ALIVE(VisitForTypeOf(expr->expression()));
   10313   HValue* value = Pop();
   10314   HInstruction* instr = New<HTypeof>(value);
   10315   return ast_context()->ReturnInstruction(instr, expr->id());
   10316 }
   10317 
   10318 
   10319 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) {
   10320   if (ast_context()->IsTest()) {
   10321     TestContext* context = TestContext::cast(ast_context());
   10322     VisitForControl(expr->expression(),
   10323                     context->if_false(),
   10324                     context->if_true());
   10325     return;
   10326   }
   10327 
   10328   if (ast_context()->IsEffect()) {
   10329     VisitForEffect(expr->expression());
   10330     return;
   10331   }
   10332 
   10333   DCHECK(ast_context()->IsValue());
   10334   HBasicBlock* materialize_false = graph()->CreateBasicBlock();
   10335   HBasicBlock* materialize_true = graph()->CreateBasicBlock();
   10336   CHECK_BAILOUT(VisitForControl(expr->expression(),
   10337                                 materialize_false,
   10338                                 materialize_true));
   10339 
   10340   if (materialize_false->HasPredecessor()) {
   10341     materialize_false->SetJoinId(expr->MaterializeFalseId());
   10342     set_current_block(materialize_false);
   10343     Push(graph()->GetConstantFalse());
   10344   } else {
   10345     materialize_false = NULL;
   10346   }
   10347 
   10348   if (materialize_true->HasPredecessor()) {
   10349     materialize_true->SetJoinId(expr->MaterializeTrueId());
   10350     set_current_block(materialize_true);
   10351     Push(graph()->GetConstantTrue());
   10352   } else {
   10353     materialize_true = NULL;
   10354   }
   10355 
   10356   HBasicBlock* join =
   10357     CreateJoin(materialize_false, materialize_true, expr->id());
   10358   set_current_block(join);
   10359   if (join != NULL) return ast_context()->ReturnValue(Pop());
   10360 }
   10361 
   10362 static Representation RepresentationFor(AstType* type) {
   10363   DisallowHeapAllocation no_allocation;
   10364   if (type->Is(AstType::None())) return Representation::None();
   10365   if (type->Is(AstType::SignedSmall())) return Representation::Smi();
   10366   if (type->Is(AstType::Signed32())) return Representation::Integer32();
   10367   if (type->Is(AstType::Number())) return Representation::Double();
   10368   return Representation::Tagged();
   10369 }
   10370 
   10371 HInstruction* HOptimizedGraphBuilder::BuildIncrement(CountOperation* expr) {
   10372   // The input to the count operation is on top of the expression stack.
   10373   Representation rep = RepresentationFor(expr->type());
   10374   if (rep.IsNone() || rep.IsTagged()) {
   10375     rep = Representation::Smi();
   10376   }
   10377 
   10378   // We need an explicit HValue representing ToNumber(input).  The
   10379   // actual HChange instruction we need is (sometimes) added in a later
   10380   // phase, so it is not available now to be used as an input to HAdd and
   10381   // as the return value.
   10382   HInstruction* number_input = AddUncasted<HForceRepresentation>(Pop(), rep);
   10383   if (!rep.IsDouble()) {
   10384     number_input->SetFlag(HInstruction::kFlexibleRepresentation);
   10385     number_input->SetFlag(HInstruction::kCannotBeTagged);
   10386   }
   10387   Push(number_input);
   10388 
   10389   // The addition has no side effects, so we do not need
   10390   // to simulate the expression stack after this instruction.
   10391   // Any later failures deopt to the load of the input or earlier.
   10392   HConstant* delta = (expr->op() == Token::INC)
   10393       ? graph()->GetConstant1()
   10394       : graph()->GetConstantMinus1();
   10395   HInstruction* instr = AddUncasted<HAdd>(Top(), delta);
   10396   if (instr->IsAdd()) {
   10397     HAdd* add = HAdd::cast(instr);
   10398     add->set_observed_input_representation(1, rep);
   10399     add->set_observed_input_representation(2, Representation::Smi());
   10400   }
   10401   instr->ClearAllSideEffects();
   10402   instr->SetFlag(HInstruction::kCannotBeTagged);
   10403   return instr;
   10404 }
   10405 
   10406 void HOptimizedGraphBuilder::BuildStoreForEffect(
   10407     Expression* expr, Property* prop, FeedbackVectorSlot slot, BailoutId ast_id,
   10408     BailoutId return_id, HValue* object, HValue* key, HValue* value) {
   10409   EffectContext for_effect(this);
   10410   Push(object);
   10411   if (key != NULL) Push(key);
   10412   Push(value);
   10413   BuildStore(expr, prop, slot, ast_id, return_id);
   10414 }
   10415 
   10416 
   10417 void HOptimizedGraphBuilder::VisitCountOperation(CountOperation* expr) {
   10418   DCHECK(!HasStackOverflow());
   10419   DCHECK(current_block() != NULL);
   10420   DCHECK(current_block()->HasPredecessor());
   10421   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   10422   Expression* target = expr->expression();
   10423   VariableProxy* proxy = target->AsVariableProxy();
   10424   Property* prop = target->AsProperty();
   10425   if (proxy == NULL && prop == NULL) {
   10426     return Bailout(kInvalidLhsInCountOperation);
   10427   }
   10428 
   10429   // Match the full code generator stack by simulating an extra stack
   10430   // element for postfix operations in a non-effect context.  The return
   10431   // value is ToNumber(input).
   10432   bool returns_original_input =
   10433       expr->is_postfix() && !ast_context()->IsEffect();
   10434   HValue* input = NULL;  // ToNumber(original_input).
   10435   HValue* after = NULL;  // The result after incrementing or decrementing.
   10436 
   10437   if (proxy != NULL) {
   10438     Variable* var = proxy->var();
   10439     if (var->mode() == CONST) {
   10440       return Bailout(kNonInitializerAssignmentToConst);
   10441     }
   10442     // Argument of the count operation is a variable, not a property.
   10443     DCHECK(prop == NULL);
   10444     CHECK_ALIVE(VisitForValue(target));
   10445 
   10446     after = BuildIncrement(expr);
   10447     input = returns_original_input ? Top() : Pop();
   10448     Push(after);
   10449 
   10450     switch (var->location()) {
   10451       case VariableLocation::UNALLOCATED:
   10452         HandleGlobalVariableAssignment(var, after, expr->CountSlot(),
   10453                                        expr->AssignmentId());
   10454         break;
   10455 
   10456       case VariableLocation::PARAMETER:
   10457       case VariableLocation::LOCAL:
   10458         BindIfLive(var, after);
   10459         break;
   10460 
   10461       case VariableLocation::CONTEXT: {
   10462         HValue* context = BuildContextChainWalk(var);
   10463         HStoreContextSlot::Mode mode = IsLexicalVariableMode(var->mode())
   10464             ? HStoreContextSlot::kCheckDeoptimize : HStoreContextSlot::kNoCheck;
   10465         HStoreContextSlot* instr = Add<HStoreContextSlot>(context, var->index(),
   10466                                                           mode, after);
   10467         if (instr->HasObservableSideEffects()) {
   10468           Add<HSimulate>(expr->AssignmentId(), REMOVABLE_SIMULATE);
   10469         }
   10470         break;
   10471       }
   10472 
   10473       case VariableLocation::LOOKUP:
   10474         return Bailout(kLookupVariableInCountOperation);
   10475 
   10476       case VariableLocation::MODULE:
   10477         UNREACHABLE();
   10478     }
   10479 
   10480     Drop(returns_original_input ? 2 : 1);
   10481     return ast_context()->ReturnValue(expr->is_postfix() ? input : after);
   10482   }
   10483 
   10484   // Argument of the count operation is a property.
   10485   DCHECK(prop != NULL);
   10486   if (returns_original_input) Push(graph()->GetConstantUndefined());
   10487 
   10488   CHECK_ALIVE(VisitForValue(prop->obj()));
   10489   HValue* object = Top();
   10490 
   10491   HValue* key = NULL;
   10492   if (!prop->key()->IsPropertyName() || prop->IsStringAccess()) {
   10493     CHECK_ALIVE(VisitForValue(prop->key()));
   10494     key = Top();
   10495   }
   10496 
   10497   CHECK_ALIVE(PushLoad(prop, object, key));
   10498 
   10499   after = BuildIncrement(expr);
   10500 
   10501   if (returns_original_input) {
   10502     input = Pop();
   10503     // Drop object and key to push it again in the effect context below.
   10504     Drop(key == NULL ? 1 : 2);
   10505     environment()->SetExpressionStackAt(0, input);
   10506     CHECK_ALIVE(BuildStoreForEffect(expr, prop, expr->CountSlot(), expr->id(),
   10507                                     expr->AssignmentId(), object, key, after));
   10508     return ast_context()->ReturnValue(Pop());
   10509   }
   10510 
   10511   environment()->SetExpressionStackAt(0, after);
   10512   return BuildStore(expr, prop, expr->CountSlot(), expr->id(),
   10513                     expr->AssignmentId());
   10514 }
   10515 
   10516 
   10517 HInstruction* HOptimizedGraphBuilder::BuildStringCharCodeAt(
   10518     HValue* string,
   10519     HValue* index) {
   10520   if (string->IsConstant() && index->IsConstant()) {
   10521     HConstant* c_string = HConstant::cast(string);
   10522     HConstant* c_index = HConstant::cast(index);
   10523     if (c_string->HasStringValue() && c_index->HasNumberValue()) {
   10524       int32_t i = c_index->NumberValueAsInteger32();
   10525       Handle<String> s = c_string->StringValue();
   10526       if (i < 0 || i >= s->length()) {
   10527         return New<HConstant>(std::numeric_limits<double>::quiet_NaN());
   10528       }
   10529       return New<HConstant>(s->Get(i));
   10530     }
   10531   }
   10532   string = BuildCheckString(string);
   10533   index = Add<HBoundsCheck>(index, AddLoadStringLength(string));
   10534   return New<HStringCharCodeAt>(string, index);
   10535 }
   10536 
   10537 
   10538 // Checks if the given shift amounts have following forms:
   10539 // (N1) and (N2) with N1 + N2 = 32; (sa) and (32 - sa).
   10540 static bool ShiftAmountsAllowReplaceByRotate(HValue* sa,
   10541                                              HValue* const32_minus_sa) {
   10542   if (sa->IsConstant() && const32_minus_sa->IsConstant()) {
   10543     const HConstant* c1 = HConstant::cast(sa);
   10544     const HConstant* c2 = HConstant::cast(const32_minus_sa);
   10545     return c1->HasInteger32Value() && c2->HasInteger32Value() &&
   10546         (c1->Integer32Value() + c2->Integer32Value() == 32);
   10547   }
   10548   if (!const32_minus_sa->IsSub()) return false;
   10549   HSub* sub = HSub::cast(const32_minus_sa);
   10550   return sub->left()->EqualsInteger32Constant(32) && sub->right() == sa;
   10551 }
   10552 
   10553 
   10554 // Checks if the left and the right are shift instructions with the oposite
   10555 // directions that can be replaced by one rotate right instruction or not.
   10556 // Returns the operand and the shift amount for the rotate instruction in the
   10557 // former case.
   10558 bool HGraphBuilder::MatchRotateRight(HValue* left,
   10559                                      HValue* right,
   10560                                      HValue** operand,
   10561                                      HValue** shift_amount) {
   10562   HShl* shl;
   10563   HShr* shr;
   10564   if (left->IsShl() && right->IsShr()) {
   10565     shl = HShl::cast(left);
   10566     shr = HShr::cast(right);
   10567   } else if (left->IsShr() && right->IsShl()) {
   10568     shl = HShl::cast(right);
   10569     shr = HShr::cast(left);
   10570   } else {
   10571     return false;
   10572   }
   10573   if (shl->left() != shr->left()) return false;
   10574 
   10575   if (!ShiftAmountsAllowReplaceByRotate(shl->right(), shr->right()) &&
   10576       !ShiftAmountsAllowReplaceByRotate(shr->right(), shl->right())) {
   10577     return false;
   10578   }
   10579   *operand = shr->left();
   10580   *shift_amount = shr->right();
   10581   return true;
   10582 }
   10583 
   10584 
   10585 bool CanBeZero(HValue* right) {
   10586   if (right->IsConstant()) {
   10587     HConstant* right_const = HConstant::cast(right);
   10588     if (right_const->HasInteger32Value() &&
   10589        (right_const->Integer32Value() & 0x1f) != 0) {
   10590       return false;
   10591     }
   10592   }
   10593   return true;
   10594 }
   10595 
   10596 HValue* HGraphBuilder::EnforceNumberType(HValue* number, AstType* expected) {
   10597   if (expected->Is(AstType::SignedSmall())) {
   10598     return AddUncasted<HForceRepresentation>(number, Representation::Smi());
   10599   }
   10600   if (expected->Is(AstType::Signed32())) {
   10601     return AddUncasted<HForceRepresentation>(number,
   10602                                              Representation::Integer32());
   10603   }
   10604   return number;
   10605 }
   10606 
   10607 HValue* HGraphBuilder::TruncateToNumber(HValue* value, AstType** expected) {
   10608   if (value->IsConstant()) {
   10609     HConstant* constant = HConstant::cast(value);
   10610     Maybe<HConstant*> number =
   10611         constant->CopyToTruncatedNumber(isolate(), zone());
   10612     if (number.IsJust()) {
   10613       *expected = AstType::Number();
   10614       return AddInstruction(number.FromJust());
   10615     }
   10616   }
   10617 
   10618   // We put temporary values on the stack, which don't correspond to anything
   10619   // in baseline code. Since nothing is observable we avoid recording those
   10620   // pushes with a NoObservableSideEffectsScope.
   10621   NoObservableSideEffectsScope no_effects(this);
   10622 
   10623   AstType* expected_type = *expected;
   10624 
   10625   // Separate the number type from the rest.
   10626   AstType* expected_obj =
   10627       AstType::Intersect(expected_type, AstType::NonNumber(), zone());
   10628   AstType* expected_number =
   10629       AstType::Intersect(expected_type, AstType::Number(), zone());
   10630 
   10631   // We expect to get a number.
   10632   // (We need to check first, since AstType::None->Is(AstType::Any()) == true.
   10633   if (expected_obj->Is(AstType::None())) {
   10634     DCHECK(!expected_number->Is(AstType::None()));
   10635     return value;
   10636   }
   10637 
   10638   if (expected_obj->Is(AstType::Undefined())) {
   10639     // This is already done by HChange.
   10640     *expected = AstType::Union(expected_number, AstType::Number(), zone());
   10641     return value;
   10642   }
   10643 
   10644   return value;
   10645 }
   10646 
   10647 
   10648 HValue* HOptimizedGraphBuilder::BuildBinaryOperation(
   10649     BinaryOperation* expr,
   10650     HValue* left,
   10651     HValue* right,
   10652     PushBeforeSimulateBehavior push_sim_result) {
   10653   AstType* left_type = bounds_.get(expr->left()).lower;
   10654   AstType* right_type = bounds_.get(expr->right()).lower;
   10655   AstType* result_type = bounds_.get(expr).lower;
   10656   Maybe<int> fixed_right_arg = expr->fixed_right_arg();
   10657   Handle<AllocationSite> allocation_site = expr->allocation_site();
   10658 
   10659   HAllocationMode allocation_mode;
   10660   if (FLAG_allocation_site_pretenuring && !allocation_site.is_null()) {
   10661     allocation_mode = HAllocationMode(allocation_site);
   10662   }
   10663   HValue* result = HGraphBuilder::BuildBinaryOperation(
   10664       expr->op(), left, right, left_type, right_type, result_type,
   10665       fixed_right_arg, allocation_mode, expr->id());
   10666   // Add a simulate after instructions with observable side effects, and
   10667   // after phis, which are the result of BuildBinaryOperation when we
   10668   // inlined some complex subgraph.
   10669   if (result->HasObservableSideEffects() || result->IsPhi()) {
   10670     if (push_sim_result == PUSH_BEFORE_SIMULATE) {
   10671       Push(result);
   10672       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   10673       Drop(1);
   10674     } else {
   10675       Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE);
   10676     }
   10677   }
   10678   return result;
   10679 }
   10680 
   10681 HValue* HGraphBuilder::BuildBinaryOperation(
   10682     Token::Value op, HValue* left, HValue* right, AstType* left_type,
   10683     AstType* right_type, AstType* result_type, Maybe<int> fixed_right_arg,
   10684     HAllocationMode allocation_mode, BailoutId opt_id) {
   10685   bool maybe_string_add = false;
   10686   if (op == Token::ADD) {
   10687     // If we are adding constant string with something for which we don't have
   10688     // a feedback yet, assume that it's also going to be a string and don't
   10689     // generate deopt instructions.
   10690     if (!left_type->IsInhabited() && right->IsConstant() &&
   10691         HConstant::cast(right)->HasStringValue()) {
   10692       left_type = AstType::String();
   10693     }
   10694 
   10695     if (!right_type->IsInhabited() && left->IsConstant() &&
   10696         HConstant::cast(left)->HasStringValue()) {
   10697       right_type = AstType::String();
   10698     }
   10699 
   10700     maybe_string_add = (left_type->Maybe(AstType::String()) ||
   10701                         left_type->Maybe(AstType::Receiver()) ||
   10702                         right_type->Maybe(AstType::String()) ||
   10703                         right_type->Maybe(AstType::Receiver()));
   10704   }
   10705 
   10706   Representation left_rep = RepresentationFor(left_type);
   10707   Representation right_rep = RepresentationFor(right_type);
   10708 
   10709   if (!left_type->IsInhabited()) {
   10710     Add<HDeoptimize>(
   10711         DeoptimizeReason::kInsufficientTypeFeedbackForLHSOfBinaryOperation,
   10712         Deoptimizer::SOFT);
   10713     left_type = AstType::Any();
   10714     left_rep = RepresentationFor(left_type);
   10715     maybe_string_add = op == Token::ADD;
   10716   }
   10717 
   10718   if (!right_type->IsInhabited()) {
   10719     Add<HDeoptimize>(
   10720         DeoptimizeReason::kInsufficientTypeFeedbackForRHSOfBinaryOperation,
   10721         Deoptimizer::SOFT);
   10722     right_type = AstType::Any();
   10723     right_rep = RepresentationFor(right_type);
   10724     maybe_string_add = op == Token::ADD;
   10725   }
   10726 
   10727   if (!maybe_string_add) {
   10728     left = TruncateToNumber(left, &left_type);
   10729     right = TruncateToNumber(right, &right_type);
   10730   }
   10731 
   10732   // Special case for string addition here.
   10733   if (op == Token::ADD &&
   10734       (left_type->Is(AstType::String()) || right_type->Is(AstType::String()))) {
   10735     // Validate type feedback for left argument.
   10736     if (left_type->Is(AstType::String())) {
   10737       left = BuildCheckString(left);
   10738     }
   10739 
   10740     // Validate type feedback for right argument.
   10741     if (right_type->Is(AstType::String())) {
   10742       right = BuildCheckString(right);
   10743     }
   10744 
   10745     // Convert left argument as necessary.
   10746     if (left_type->Is(AstType::Number())) {
   10747       DCHECK(right_type->Is(AstType::String()));
   10748       left = BuildNumberToString(left, left_type);
   10749     } else if (!left_type->Is(AstType::String())) {
   10750       DCHECK(right_type->Is(AstType::String()));
   10751       return AddUncasted<HStringAdd>(
   10752           left, right, allocation_mode.GetPretenureMode(),
   10753           STRING_ADD_CONVERT_LEFT, allocation_mode.feedback_site());
   10754     }
   10755 
   10756     // Convert right argument as necessary.
   10757     if (right_type->Is(AstType::Number())) {
   10758       DCHECK(left_type->Is(AstType::String()));
   10759       right = BuildNumberToString(right, right_type);
   10760     } else if (!right_type->Is(AstType::String())) {
   10761       DCHECK(left_type->Is(AstType::String()));
   10762       return AddUncasted<HStringAdd>(
   10763           left, right, allocation_mode.GetPretenureMode(),
   10764           STRING_ADD_CONVERT_RIGHT, allocation_mode.feedback_site());
   10765     }
   10766 
   10767     // Fast paths for empty constant strings.
   10768     Handle<String> left_string =
   10769         left->IsConstant() && HConstant::cast(left)->HasStringValue()
   10770             ? HConstant::cast(left)->StringValue()
   10771             : Handle<String>();
   10772     Handle<String> right_string =
   10773         right->IsConstant() && HConstant::cast(right)->HasStringValue()
   10774             ? HConstant::cast(right)->StringValue()
   10775             : Handle<String>();
   10776     if (!left_string.is_null() && left_string->length() == 0) return right;
   10777     if (!right_string.is_null() && right_string->length() == 0) return left;
   10778     if (!left_string.is_null() && !right_string.is_null()) {
   10779       return AddUncasted<HStringAdd>(
   10780           left, right, allocation_mode.GetPretenureMode(),
   10781           STRING_ADD_CHECK_NONE, allocation_mode.feedback_site());
   10782     }
   10783 
   10784     // Register the dependent code with the allocation site.
   10785     if (!allocation_mode.feedback_site().is_null()) {
   10786       DCHECK(!graph()->info()->IsStub());
   10787       Handle<AllocationSite> site(allocation_mode.feedback_site());
   10788       top_info()->dependencies()->AssumeTenuringDecision(site);
   10789     }
   10790 
   10791     // Inline the string addition into the stub when creating allocation
   10792     // mementos to gather allocation site feedback, or if we can statically
   10793     // infer that we're going to create a cons string.
   10794     if ((graph()->info()->IsStub() &&
   10795          allocation_mode.CreateAllocationMementos()) ||
   10796         (left->IsConstant() &&
   10797          HConstant::cast(left)->HasStringValue() &&
   10798          HConstant::cast(left)->StringValue()->length() + 1 >=
   10799            ConsString::kMinLength) ||
   10800         (right->IsConstant() &&
   10801          HConstant::cast(right)->HasStringValue() &&
   10802          HConstant::cast(right)->StringValue()->length() + 1 >=
   10803            ConsString::kMinLength)) {
   10804       return BuildStringAdd(left, right, allocation_mode);
   10805     }
   10806 
   10807     // Fallback to using the string add stub.
   10808     return AddUncasted<HStringAdd>(
   10809         left, right, allocation_mode.GetPretenureMode(), STRING_ADD_CHECK_NONE,
   10810         allocation_mode.feedback_site());
   10811   }
   10812 
   10813   // Special case for +x here.
   10814   if (op == Token::MUL) {
   10815     if (left->EqualsInteger32Constant(1)) {
   10816       return BuildToNumber(right);
   10817     }
   10818     if (right->EqualsInteger32Constant(1)) {
   10819       return BuildToNumber(left);
   10820     }
   10821   }
   10822 
   10823   if (graph()->info()->IsStub()) {
   10824     left = EnforceNumberType(left, left_type);
   10825     right = EnforceNumberType(right, right_type);
   10826   }
   10827 
   10828   Representation result_rep = RepresentationFor(result_type);
   10829 
   10830   bool is_non_primitive = (left_rep.IsTagged() && !left_rep.IsSmi()) ||
   10831                           (right_rep.IsTagged() && !right_rep.IsSmi());
   10832 
   10833   HInstruction* instr = NULL;
   10834   // Only the stub is allowed to call into the runtime, since otherwise we would
   10835   // inline several instructions (including the two pushes) for every tagged
   10836   // operation in optimized code, which is more expensive, than a stub call.
   10837   if (graph()->info()->IsStub() && is_non_primitive) {
   10838     HValue* values[] = {left, right};
   10839 #define GET_STUB(Name)                                                       \
   10840   do {                                                                       \
   10841     Callable callable = CodeFactory::Name(isolate());                        \
   10842     HValue* stub = Add<HConstant>(callable.code());                          \
   10843     instr = AddUncasted<HCallWithDescriptor>(stub, 0, callable.descriptor(), \
   10844                                              ArrayVector(values));           \
   10845   } while (false)
   10846 
   10847     switch (op) {
   10848       default:
   10849         UNREACHABLE();
   10850       case Token::ADD:
   10851         GET_STUB(Add);
   10852         break;
   10853       case Token::SUB:
   10854         GET_STUB(Subtract);
   10855         break;
   10856       case Token::MUL:
   10857         GET_STUB(Multiply);
   10858         break;
   10859       case Token::DIV:
   10860         GET_STUB(Divide);
   10861         break;
   10862       case Token::MOD:
   10863         GET_STUB(Modulus);
   10864         break;
   10865       case Token::BIT_OR:
   10866         GET_STUB(BitwiseOr);
   10867         break;
   10868       case Token::BIT_AND:
   10869         GET_STUB(BitwiseAnd);
   10870         break;
   10871       case Token::BIT_XOR:
   10872         GET_STUB(BitwiseXor);
   10873         break;
   10874       case Token::SAR:
   10875         GET_STUB(ShiftRight);
   10876         break;
   10877       case Token::SHR:
   10878         GET_STUB(ShiftRightLogical);
   10879         break;
   10880       case Token::SHL:
   10881         GET_STUB(ShiftLeft);
   10882         break;
   10883     }
   10884 #undef GET_STUB
   10885   } else {
   10886     switch (op) {
   10887       case Token::ADD:
   10888         instr = AddUncasted<HAdd>(left, right);
   10889         break;
   10890       case Token::SUB:
   10891         instr = AddUncasted<HSub>(left, right);
   10892         break;
   10893       case Token::MUL:
   10894         instr = AddUncasted<HMul>(left, right);
   10895         break;
   10896       case Token::MOD: {
   10897         if (fixed_right_arg.IsJust() &&
   10898             !right->EqualsInteger32Constant(fixed_right_arg.FromJust())) {
   10899           HConstant* fixed_right =
   10900               Add<HConstant>(static_cast<int>(fixed_right_arg.FromJust()));
   10901           IfBuilder if_same(this);
   10902           if_same.If<HCompareNumericAndBranch>(right, fixed_right, Token::EQ);
   10903           if_same.Then();
   10904           if_same.ElseDeopt(DeoptimizeReason::kUnexpectedRHSOfBinaryOperation);
   10905           right = fixed_right;
   10906         }
   10907         instr = AddUncasted<HMod>(left, right);
   10908         break;
   10909       }
   10910       case Token::DIV:
   10911         instr = AddUncasted<HDiv>(left, right);
   10912         break;
   10913       case Token::BIT_XOR:
   10914       case Token::BIT_AND:
   10915         instr = AddUncasted<HBitwise>(op, left, right);
   10916         break;
   10917       case Token::BIT_OR: {
   10918         HValue *operand, *shift_amount;
   10919         if (left_type->Is(AstType::Signed32()) &&
   10920             right_type->Is(AstType::Signed32()) &&
   10921             MatchRotateRight(left, right, &operand, &shift_amount)) {
   10922           instr = AddUncasted<HRor>(operand, shift_amount);
   10923         } else {
   10924           instr = AddUncasted<HBitwise>(op, left, right);
   10925         }
   10926         break;
   10927       }
   10928       case Token::SAR:
   10929         instr = AddUncasted<HSar>(left, right);
   10930         break;
   10931       case Token::SHR:
   10932         instr = AddUncasted<HShr>(left, right);
   10933         if (instr->IsShr() && CanBeZero(right)) {
   10934           graph()->RecordUint32Instruction(instr);
   10935         }
   10936         break;
   10937       case Token::SHL:
   10938         instr = AddUncasted<HShl>(left, right);
   10939         break;
   10940       default:
   10941         UNREACHABLE();
   10942     }
   10943   }
   10944 
   10945   if (instr->IsBinaryOperation()) {
   10946     HBinaryOperation* binop = HBinaryOperation::cast(instr);
   10947     binop->set_observed_input_representation(1, left_rep);
   10948     binop->set_observed_input_representation(2, right_rep);
   10949     binop->initialize_output_representation(result_rep);
   10950     if (graph()->info()->IsStub()) {
   10951       // Stub should not call into stub.
   10952       instr->SetFlag(HValue::kCannotBeTagged);
   10953       // And should truncate on HForceRepresentation already.
   10954       if (left->IsForceRepresentation()) {
   10955         left->CopyFlag(HValue::kTruncatingToSmi, instr);
   10956         left->CopyFlag(HValue::kTruncatingToInt32, instr);
   10957       }
   10958       if (right->IsForceRepresentation()) {
   10959         right->CopyFlag(HValue::kTruncatingToSmi, instr);
   10960         right->CopyFlag(HValue::kTruncatingToInt32, instr);
   10961       }
   10962     }
   10963   }
   10964   return instr;
   10965 }
   10966 
   10967 
   10968 // Check for the form (%_ClassOf(foo) === 'BarClass').
   10969 static bool IsClassOfTest(CompareOperation* expr) {
   10970   if (expr->op() != Token::EQ_STRICT) return false;
   10971   CallRuntime* call = expr->left()->AsCallRuntime();
   10972   if (call == NULL) return false;
   10973   Literal* literal = expr->right()->AsLiteral();
   10974   if (literal == NULL) return false;
   10975   if (!literal->value()->IsString()) return false;
   10976   if (!call->is_jsruntime() &&
   10977       call->function()->function_id != Runtime::kInlineClassOf) {
   10978     return false;
   10979   }
   10980   DCHECK(call->arguments()->length() == 1);
   10981   return true;
   10982 }
   10983 
   10984 
   10985 void HOptimizedGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
   10986   DCHECK(!HasStackOverflow());
   10987   DCHECK(current_block() != NULL);
   10988   DCHECK(current_block()->HasPredecessor());
   10989   switch (expr->op()) {
   10990     case Token::COMMA:
   10991       return VisitComma(expr);
   10992     case Token::OR:
   10993     case Token::AND:
   10994       return VisitLogicalExpression(expr);
   10995     default:
   10996       return VisitArithmeticExpression(expr);
   10997   }
   10998 }
   10999 
   11000 
   11001 void HOptimizedGraphBuilder::VisitComma(BinaryOperation* expr) {
   11002   CHECK_ALIVE(VisitForEffect(expr->left()));
   11003   // Visit the right subexpression in the same AST context as the entire
   11004   // expression.
   11005   Visit(expr->right());
   11006 }
   11007 
   11008 
   11009 void HOptimizedGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) {
   11010   bool is_logical_and = expr->op() == Token::AND;
   11011   if (ast_context()->IsTest()) {
   11012     TestContext* context = TestContext::cast(ast_context());
   11013     // Translate left subexpression.
   11014     HBasicBlock* eval_right = graph()->CreateBasicBlock();
   11015     if (is_logical_and) {
   11016       CHECK_BAILOUT(VisitForControl(expr->left(),
   11017                                     eval_right,
   11018                                     context->if_false()));
   11019     } else {
   11020       CHECK_BAILOUT(VisitForControl(expr->left(),
   11021                                     context->if_true(),
   11022                                     eval_right));
   11023     }
   11024 
   11025     // Translate right subexpression by visiting it in the same AST
   11026     // context as the entire expression.
   11027     CHECK(eval_right->HasPredecessor());
   11028     eval_right->SetJoinId(expr->RightId());
   11029     set_current_block(eval_right);
   11030     Visit(expr->right());
   11031   } else if (ast_context()->IsValue()) {
   11032     CHECK_ALIVE(VisitForValue(expr->left()));
   11033     DCHECK(current_block() != NULL);
   11034     HValue* left_value = Top();
   11035 
   11036     // Short-circuit left values that always evaluate to the same boolean value.
   11037     if (expr->left()->ToBooleanIsTrue() || expr->left()->ToBooleanIsFalse()) {
   11038       // l (evals true)  && r -> r
   11039       // l (evals true)  || r -> l
   11040       // l (evals false) && r -> l
   11041       // l (evals false) || r -> r
   11042       if (is_logical_and == expr->left()->ToBooleanIsTrue()) {
   11043         Drop(1);
   11044         CHECK_ALIVE(VisitForValue(expr->right()));
   11045       }
   11046       return ast_context()->ReturnValue(Pop());
   11047     }
   11048 
   11049     // We need an extra block to maintain edge-split form.
   11050     HBasicBlock* empty_block = graph()->CreateBasicBlock();
   11051     HBasicBlock* eval_right = graph()->CreateBasicBlock();
   11052     ToBooleanHints expected(expr->left()->to_boolean_types());
   11053     HBranch* test = is_logical_and
   11054         ? New<HBranch>(left_value, expected, eval_right, empty_block)
   11055         : New<HBranch>(left_value, expected, empty_block, eval_right);
   11056     FinishCurrentBlock(test);
   11057 
   11058     set_current_block(eval_right);
   11059     Drop(1);  // Value of the left subexpression.
   11060     CHECK_BAILOUT(VisitForValue(expr->right()));
   11061 
   11062     HBasicBlock* join_block =
   11063       CreateJoin(empty_block, current_block(), expr->id());
   11064     set_current_block(join_block);
   11065     return ast_context()->ReturnValue(Pop());
   11066 
   11067   } else {
   11068     DCHECK(ast_context()->IsEffect());
   11069     // In an effect context, we don't need the value of the left subexpression,
   11070     // only its control flow and side effects.  We need an extra block to
   11071     // maintain edge-split form.
   11072     HBasicBlock* empty_block = graph()->CreateBasicBlock();
   11073     HBasicBlock* right_block = graph()->CreateBasicBlock();
   11074     if (is_logical_and) {
   11075       CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
   11076     } else {
   11077       CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
   11078     }
   11079 
   11080     // TODO(kmillikin): Find a way to fix this.  It's ugly that there are
   11081     // actually two empty blocks (one here and one inserted by
   11082     // TestContext::BuildBranch, and that they both have an HSimulate though the
   11083     // second one is not a merge node, and that we really have no good AST ID to
   11084     // put on that first HSimulate.
   11085 
   11086     // Technically, we should be able to handle the case when one side of
   11087     // the test is not connected, but this can trip up liveness analysis
   11088     // if we did not fully connect the test context based on some optimistic
   11089     // assumption. If such an assumption was violated, we would end up with
   11090     // an environment with optimized-out values. So we should always
   11091     // conservatively connect the test context.
   11092 
   11093     CHECK(right_block->HasPredecessor());
   11094     CHECK(empty_block->HasPredecessor());
   11095 
   11096     empty_block->SetJoinId(expr->id());
   11097 
   11098     right_block->SetJoinId(expr->RightId());
   11099     set_current_block(right_block);
   11100     CHECK_BAILOUT(VisitForEffect(expr->right()));
   11101     right_block = current_block();
   11102 
   11103     HBasicBlock* join_block =
   11104       CreateJoin(empty_block, right_block, expr->id());
   11105     set_current_block(join_block);
   11106     // We did not materialize any value in the predecessor environments,
   11107     // so there is no need to handle it here.
   11108   }
   11109 }
   11110 
   11111 
   11112 void HOptimizedGraphBuilder::VisitArithmeticExpression(BinaryOperation* expr) {
   11113   CHECK_ALIVE(VisitForValue(expr->left()));
   11114   CHECK_ALIVE(VisitForValue(expr->right()));
   11115   SetSourcePosition(expr->position());
   11116   HValue* right = Pop();
   11117   HValue* left = Pop();
   11118   HValue* result =
   11119       BuildBinaryOperation(expr, left, right,
   11120           ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
   11121                                     : PUSH_BEFORE_SIMULATE);
   11122   return ast_context()->ReturnValue(result);
   11123 }
   11124 
   11125 
   11126 void HOptimizedGraphBuilder::HandleLiteralCompareTypeof(CompareOperation* expr,
   11127                                                         Expression* sub_expr,
   11128                                                         Handle<String> check) {
   11129   CHECK_ALIVE(VisitForTypeOf(sub_expr));
   11130   SetSourcePosition(expr->position());
   11131   HValue* value = Pop();
   11132   HTypeofIsAndBranch* instr = New<HTypeofIsAndBranch>(value, check);
   11133   return ast_context()->ReturnControl(instr, expr->id());
   11134 }
   11135 
   11136 namespace {
   11137 
   11138 bool IsLiteralCompareStrict(Isolate* isolate, HValue* left, Token::Value op,
   11139                             HValue* right) {
   11140   return op == Token::EQ_STRICT &&
   11141          ((left->IsConstant() &&
   11142            !HConstant::cast(left)->handle(isolate)->IsNumber() &&
   11143            !HConstant::cast(left)->handle(isolate)->IsSimd128Value() &&
   11144            !HConstant::cast(left)->handle(isolate)->IsString()) ||
   11145           (right->IsConstant() &&
   11146            !HConstant::cast(right)->handle(isolate)->IsNumber() &&
   11147            !HConstant::cast(right)->handle(isolate)->IsSimd128Value() &&
   11148            !HConstant::cast(right)->handle(isolate)->IsString()));
   11149 }
   11150 
   11151 }  // namespace
   11152 
   11153 void HOptimizedGraphBuilder::VisitCompareOperation(CompareOperation* expr) {
   11154   DCHECK(!HasStackOverflow());
   11155   DCHECK(current_block() != NULL);
   11156   DCHECK(current_block()->HasPredecessor());
   11157 
   11158   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   11159 
   11160   // Check for a few fast cases. The AST visiting behavior must be in sync
   11161   // with the full codegen: We don't push both left and right values onto
   11162   // the expression stack when one side is a special-case literal.
   11163   Expression* sub_expr = NULL;
   11164   Handle<String> check;
   11165   if (expr->IsLiteralCompareTypeof(&sub_expr, &check)) {
   11166     return HandleLiteralCompareTypeof(expr, sub_expr, check);
   11167   }
   11168   if (expr->IsLiteralCompareUndefined(&sub_expr)) {
   11169     return HandleLiteralCompareNil(expr, sub_expr, kUndefinedValue);
   11170   }
   11171   if (expr->IsLiteralCompareNull(&sub_expr)) {
   11172     return HandleLiteralCompareNil(expr, sub_expr, kNullValue);
   11173   }
   11174 
   11175   if (IsClassOfTest(expr)) {
   11176     CallRuntime* call = expr->left()->AsCallRuntime();
   11177     DCHECK(call->arguments()->length() == 1);
   11178     CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11179     HValue* value = Pop();
   11180     Literal* literal = expr->right()->AsLiteral();
   11181     Handle<String> rhs = Handle<String>::cast(literal->value());
   11182     HClassOfTestAndBranch* instr = New<HClassOfTestAndBranch>(value, rhs);
   11183     return ast_context()->ReturnControl(instr, expr->id());
   11184   }
   11185 
   11186   AstType* left_type = bounds_.get(expr->left()).lower;
   11187   AstType* right_type = bounds_.get(expr->right()).lower;
   11188   AstType* combined_type = expr->combined_type();
   11189 
   11190   CHECK_ALIVE(VisitForValue(expr->left()));
   11191   CHECK_ALIVE(VisitForValue(expr->right()));
   11192 
   11193   HValue* right = Pop();
   11194   HValue* left = Pop();
   11195   Token::Value op = expr->op();
   11196 
   11197   if (IsLiteralCompareStrict(isolate(), left, op, right)) {
   11198     HCompareObjectEqAndBranch* result =
   11199         New<HCompareObjectEqAndBranch>(left, right);
   11200     return ast_context()->ReturnControl(result, expr->id());
   11201   }
   11202 
   11203   if (op == Token::INSTANCEOF) {
   11204     // Check to see if the rhs of the instanceof is a known function.
   11205     if (right->IsConstant() &&
   11206         HConstant::cast(right)->handle(isolate())->IsJSFunction()) {
   11207       Handle<JSFunction> function =
   11208           Handle<JSFunction>::cast(HConstant::cast(right)->handle(isolate()));
   11209       // Make sure that the {function} already has a meaningful initial map
   11210       // (i.e. we constructed at least one instance using the constructor
   11211       // {function}).
   11212       if (function->has_initial_map()) {
   11213         // Lookup @@hasInstance on the {function}.
   11214         Handle<Map> function_map(function->map(), isolate());
   11215         PropertyAccessInfo has_instance(
   11216             this, LOAD, function_map,
   11217             isolate()->factory()->has_instance_symbol());
   11218         // Check if we are using the Function.prototype[@@hasInstance].
   11219         if (has_instance.CanAccessMonomorphic() &&
   11220             has_instance.IsDataConstant() &&
   11221             has_instance.constant().is_identical_to(
   11222                 isolate()->function_has_instance())) {
   11223           // Add appropriate receiver map check and prototype chain
   11224           // checks to guard the @@hasInstance lookup chain.
   11225           AddCheckMap(right, function_map);
   11226           if (has_instance.has_holder()) {
   11227             Handle<JSObject> prototype(
   11228                 JSObject::cast(has_instance.map()->prototype()), isolate());
   11229             BuildCheckPrototypeMaps(prototype, has_instance.holder());
   11230           }
   11231           // Perform the prototype chain walk.
   11232           Handle<Map> initial_map(function->initial_map(), isolate());
   11233           top_info()->dependencies()->AssumeInitialMapCantChange(initial_map);
   11234           HInstruction* prototype =
   11235               Add<HConstant>(handle(initial_map->prototype(), isolate()));
   11236           HHasInPrototypeChainAndBranch* result =
   11237               New<HHasInPrototypeChainAndBranch>(left, prototype);
   11238           return ast_context()->ReturnControl(result, expr->id());
   11239         }
   11240       }
   11241     }
   11242 
   11243     Callable callable = CodeFactory::InstanceOf(isolate());
   11244     HValue* stub = Add<HConstant>(callable.code());
   11245     HValue* values[] = {left, right};
   11246     HCallWithDescriptor* result = New<HCallWithDescriptor>(
   11247         stub, 0, callable.descriptor(), ArrayVector(values));
   11248     result->set_type(HType::Boolean());
   11249     return ast_context()->ReturnInstruction(result, expr->id());
   11250 
   11251   } else if (op == Token::IN) {
   11252     Callable callable = CodeFactory::HasProperty(isolate());
   11253     HValue* stub = Add<HConstant>(callable.code());
   11254     HValue* values[] = {left, right};
   11255     HInstruction* result =
   11256         New<HCallWithDescriptor>(stub, 0, callable.descriptor(),
   11257                                  Vector<HValue*>(values, arraysize(values)));
   11258     return ast_context()->ReturnInstruction(result, expr->id());
   11259   }
   11260 
   11261   PushBeforeSimulateBehavior push_behavior =
   11262     ast_context()->IsEffect() ? NO_PUSH_BEFORE_SIMULATE
   11263                               : PUSH_BEFORE_SIMULATE;
   11264   HControlInstruction* compare = BuildCompareInstruction(
   11265       op, left, right, left_type, right_type, combined_type,
   11266       ScriptPositionToSourcePosition(expr->left()->position()),
   11267       ScriptPositionToSourcePosition(expr->right()->position()),
   11268       push_behavior, expr->id());
   11269   if (compare == NULL) return;  // Bailed out.
   11270   return ast_context()->ReturnControl(compare, expr->id());
   11271 }
   11272 
   11273 HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
   11274     Token::Value op, HValue* left, HValue* right, AstType* left_type,
   11275     AstType* right_type, AstType* combined_type, SourcePosition left_position,
   11276     SourcePosition right_position, PushBeforeSimulateBehavior push_sim_result,
   11277     BailoutId bailout_id) {
   11278   // Cases handled below depend on collected type feedback. They should
   11279   // soft deoptimize when there is no type feedback.
   11280   if (!combined_type->IsInhabited()) {
   11281     Add<HDeoptimize>(
   11282         DeoptimizeReason::
   11283             kInsufficientTypeFeedbackForCombinedTypeOfBinaryOperation,
   11284         Deoptimizer::SOFT);
   11285     combined_type = left_type = right_type = AstType::Any();
   11286   }
   11287 
   11288   Representation left_rep = RepresentationFor(left_type);
   11289   Representation right_rep = RepresentationFor(right_type);
   11290   Representation combined_rep = RepresentationFor(combined_type);
   11291 
   11292   if (combined_type->Is(AstType::Receiver())) {
   11293     if (Token::IsEqualityOp(op)) {
   11294       // HCompareObjectEqAndBranch can only deal with object, so
   11295       // exclude numbers.
   11296       if ((left->IsConstant() &&
   11297            HConstant::cast(left)->HasNumberValue()) ||
   11298           (right->IsConstant() &&
   11299            HConstant::cast(right)->HasNumberValue())) {
   11300         Add<HDeoptimize>(
   11301             DeoptimizeReason::kTypeMismatchBetweenFeedbackAndConstant,
   11302             Deoptimizer::SOFT);
   11303         // The caller expects a branch instruction, so make it happy.
   11304         return New<HBranch>(graph()->GetConstantTrue());
   11305       }
   11306       if (op == Token::EQ) {
   11307         // For abstract equality we need to check both sides are receivers.
   11308         if (combined_type->IsClass()) {
   11309           Handle<Map> map = combined_type->AsClass()->Map();
   11310           AddCheckMap(left, map);
   11311           AddCheckMap(right, map);
   11312         } else {
   11313           BuildCheckHeapObject(left);
   11314           Add<HCheckInstanceType>(left, HCheckInstanceType::IS_JS_RECEIVER);
   11315           BuildCheckHeapObject(right);
   11316           Add<HCheckInstanceType>(right, HCheckInstanceType::IS_JS_RECEIVER);
   11317         }
   11318       } else {
   11319         // For strict equality we only need to check one side.
   11320         HValue* operand_to_check =
   11321             left->block()->block_id() < right->block()->block_id() ? left
   11322                                                                    : right;
   11323         if (combined_type->IsClass()) {
   11324           Handle<Map> map = combined_type->AsClass()->Map();
   11325           AddCheckMap(operand_to_check, map);
   11326         } else {
   11327           BuildCheckHeapObject(operand_to_check);
   11328           Add<HCheckInstanceType>(operand_to_check,
   11329                                   HCheckInstanceType::IS_JS_RECEIVER);
   11330         }
   11331       }
   11332       HCompareObjectEqAndBranch* result =
   11333           New<HCompareObjectEqAndBranch>(left, right);
   11334       return result;
   11335     } else {
   11336       if (combined_type->IsClass()) {
   11337         // TODO(bmeurer): This is an optimized version of an x < y, x > y,
   11338         // x <= y or x >= y, where both x and y are spec objects with the
   11339         // same map. The CompareIC collects this map for us. So if we know
   11340         // that there's no @@toPrimitive on the map (including the prototype
   11341         // chain), and both valueOf and toString are the default initial
   11342         // implementations (on the %ObjectPrototype%), then we can reduce
   11343         // the comparison to map checks on x and y, because the comparison
   11344         // will turn into a comparison of "[object CLASS]" to itself (the
   11345         // default outcome of toString, since valueOf returns a spec object).
   11346         // This is pretty much adhoc, so in TurboFan we could do a lot better
   11347         // and inline the interesting parts of ToPrimitive (actually we could
   11348         // even do that in Crankshaft but we don't want to waste too much
   11349         // time on this now).
   11350         DCHECK(Token::IsOrderedRelationalCompareOp(op));
   11351         Handle<Map> map = combined_type->AsClass()->Map();
   11352         PropertyAccessInfo value_of(this, LOAD, map,
   11353                                     isolate()->factory()->valueOf_string());
   11354         PropertyAccessInfo to_primitive(
   11355             this, LOAD, map, isolate()->factory()->to_primitive_symbol());
   11356         PropertyAccessInfo to_string(this, LOAD, map,
   11357                                      isolate()->factory()->toString_string());
   11358         PropertyAccessInfo to_string_tag(
   11359             this, LOAD, map, isolate()->factory()->to_string_tag_symbol());
   11360         if (to_primitive.CanAccessMonomorphic() && !to_primitive.IsFound() &&
   11361             to_string_tag.CanAccessMonomorphic() &&
   11362             (!to_string_tag.IsFound() || to_string_tag.IsData() ||
   11363              to_string_tag.IsDataConstant()) &&
   11364             value_of.CanAccessMonomorphic() && value_of.IsDataConstant() &&
   11365             value_of.constant().is_identical_to(isolate()->object_value_of()) &&
   11366             to_string.CanAccessMonomorphic() && to_string.IsDataConstant() &&
   11367             to_string.constant().is_identical_to(
   11368                 isolate()->object_to_string())) {
   11369           // We depend on the prototype chain to stay the same, because we
   11370           // also need to deoptimize when someone installs @@toPrimitive
   11371           // or @@toStringTag somewhere in the prototype chain.
   11372           Handle<Object> prototype(map->prototype(), isolate());
   11373           if (prototype->IsJSObject()) {
   11374             BuildCheckPrototypeMaps(Handle<JSObject>::cast(prototype),
   11375                                     Handle<JSObject>::null());
   11376           }
   11377           AddCheckMap(left, map);
   11378           AddCheckMap(right, map);
   11379           // The caller expects a branch instruction, so make it happy.
   11380           return New<HBranch>(
   11381               graph()->GetConstantBool(op == Token::LTE || op == Token::GTE));
   11382         }
   11383       }
   11384       Bailout(kUnsupportedNonPrimitiveCompare);
   11385       return NULL;
   11386     }
   11387   } else if (combined_type->Is(AstType::InternalizedString()) &&
   11388              Token::IsEqualityOp(op)) {
   11389     // If we have a constant argument, it should be consistent with the type
   11390     // feedback (otherwise we fail assertions in HCompareObjectEqAndBranch).
   11391     if ((left->IsConstant() &&
   11392          !HConstant::cast(left)->HasInternalizedStringValue()) ||
   11393         (right->IsConstant() &&
   11394          !HConstant::cast(right)->HasInternalizedStringValue())) {
   11395       Add<HDeoptimize>(
   11396           DeoptimizeReason::kTypeMismatchBetweenFeedbackAndConstant,
   11397           Deoptimizer::SOFT);
   11398       // The caller expects a branch instruction, so make it happy.
   11399       return New<HBranch>(graph()->GetConstantTrue());
   11400     }
   11401     BuildCheckHeapObject(left);
   11402     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_INTERNALIZED_STRING);
   11403     BuildCheckHeapObject(right);
   11404     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_INTERNALIZED_STRING);
   11405     HCompareObjectEqAndBranch* result =
   11406         New<HCompareObjectEqAndBranch>(left, right);
   11407     return result;
   11408   } else if (combined_type->Is(AstType::String())) {
   11409     BuildCheckHeapObject(left);
   11410     Add<HCheckInstanceType>(left, HCheckInstanceType::IS_STRING);
   11411     BuildCheckHeapObject(right);
   11412     Add<HCheckInstanceType>(right, HCheckInstanceType::IS_STRING);
   11413     HStringCompareAndBranch* result =
   11414         New<HStringCompareAndBranch>(left, right, op);
   11415     return result;
   11416   } else if (combined_type->Is(AstType::Boolean())) {
   11417     AddCheckMap(left, isolate()->factory()->boolean_map());
   11418     AddCheckMap(right, isolate()->factory()->boolean_map());
   11419     if (Token::IsEqualityOp(op)) {
   11420       HCompareObjectEqAndBranch* result =
   11421           New<HCompareObjectEqAndBranch>(left, right);
   11422       return result;
   11423     }
   11424     left = Add<HLoadNamedField>(
   11425         left, nullptr,
   11426         HObjectAccess::ForOddballToNumber(Representation::Smi()));
   11427     right = Add<HLoadNamedField>(
   11428         right, nullptr,
   11429         HObjectAccess::ForOddballToNumber(Representation::Smi()));
   11430     HCompareNumericAndBranch* result =
   11431         New<HCompareNumericAndBranch>(left, right, op);
   11432     return result;
   11433   } else {
   11434     if (op == Token::EQ) {
   11435       if (left->IsConstant() &&
   11436           HConstant::cast(left)->GetInstanceType() == ODDBALL_TYPE &&
   11437           HConstant::cast(left)->IsUndetectable()) {
   11438         return New<HIsUndetectableAndBranch>(right);
   11439       }
   11440 
   11441       if (right->IsConstant() &&
   11442           HConstant::cast(right)->GetInstanceType() == ODDBALL_TYPE &&
   11443           HConstant::cast(right)->IsUndetectable()) {
   11444         return New<HIsUndetectableAndBranch>(left);
   11445       }
   11446     }
   11447 
   11448     if (combined_rep.IsTagged() || combined_rep.IsNone()) {
   11449       HCompareGeneric* result = Add<HCompareGeneric>(left, right, op);
   11450       result->set_observed_input_representation(1, left_rep);
   11451       result->set_observed_input_representation(2, right_rep);
   11452       if (result->HasObservableSideEffects()) {
   11453         if (push_sim_result == PUSH_BEFORE_SIMULATE) {
   11454           Push(result);
   11455           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
   11456           Drop(1);
   11457         } else {
   11458           AddSimulate(bailout_id, REMOVABLE_SIMULATE);
   11459         }
   11460       }
   11461       // TODO(jkummerow): Can we make this more efficient?
   11462       HBranch* branch = New<HBranch>(result);
   11463       return branch;
   11464     } else {
   11465       HCompareNumericAndBranch* result =
   11466           New<HCompareNumericAndBranch>(left, right, op);
   11467       result->set_observed_input_representation(left_rep, right_rep);
   11468       return result;
   11469     }
   11470   }
   11471 }
   11472 
   11473 
   11474 void HOptimizedGraphBuilder::HandleLiteralCompareNil(CompareOperation* expr,
   11475                                                      Expression* sub_expr,
   11476                                                      NilValue nil) {
   11477   DCHECK(!HasStackOverflow());
   11478   DCHECK(current_block() != NULL);
   11479   DCHECK(current_block()->HasPredecessor());
   11480   DCHECK(expr->op() == Token::EQ || expr->op() == Token::EQ_STRICT);
   11481   if (!is_tracking_positions()) SetSourcePosition(expr->position());
   11482   CHECK_ALIVE(VisitForValue(sub_expr));
   11483   HValue* value = Pop();
   11484   HControlInstruction* instr;
   11485   if (expr->op() == Token::EQ_STRICT) {
   11486     HConstant* nil_constant = nil == kNullValue
   11487         ? graph()->GetConstantNull()
   11488         : graph()->GetConstantUndefined();
   11489     instr = New<HCompareObjectEqAndBranch>(value, nil_constant);
   11490   } else {
   11491     DCHECK_EQ(Token::EQ, expr->op());
   11492     instr = New<HIsUndetectableAndBranch>(value);
   11493   }
   11494   return ast_context()->ReturnControl(instr, expr->id());
   11495 }
   11496 
   11497 
   11498 void HOptimizedGraphBuilder::VisitSpread(Spread* expr) { UNREACHABLE(); }
   11499 
   11500 
   11501 void HOptimizedGraphBuilder::VisitEmptyParentheses(EmptyParentheses* expr) {
   11502   UNREACHABLE();
   11503 }
   11504 
   11505 
   11506 HValue* HOptimizedGraphBuilder::AddThisFunction() {
   11507   return AddInstruction(BuildThisFunction());
   11508 }
   11509 
   11510 
   11511 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() {
   11512   // If we share optimized code between different closures, the
   11513   // this-function is not a constant, except inside an inlined body.
   11514   if (function_state()->outer() != NULL) {
   11515       return New<HConstant>(
   11516           function_state()->compilation_info()->closure());
   11517   } else {
   11518       return New<HThisFunction>();
   11519   }
   11520 }
   11521 
   11522 
   11523 HInstruction* HOptimizedGraphBuilder::BuildFastLiteral(
   11524     Handle<JSObject> boilerplate_object,
   11525     AllocationSiteUsageContext* site_context) {
   11526   NoObservableSideEffectsScope no_effects(this);
   11527   Handle<Map> initial_map(boilerplate_object->map());
   11528   InstanceType instance_type = initial_map->instance_type();
   11529   DCHECK(instance_type == JS_ARRAY_TYPE || instance_type == JS_OBJECT_TYPE);
   11530 
   11531   HType type = instance_type == JS_ARRAY_TYPE
   11532       ? HType::JSArray() : HType::JSObject();
   11533   HValue* object_size_constant = Add<HConstant>(initial_map->instance_size());
   11534 
   11535   PretenureFlag pretenure_flag = NOT_TENURED;
   11536   Handle<AllocationSite> top_site(*site_context->top(), isolate());
   11537   if (FLAG_allocation_site_pretenuring) {
   11538     pretenure_flag = top_site->GetPretenureMode();
   11539   }
   11540 
   11541   Handle<AllocationSite> current_site(*site_context->current(), isolate());
   11542   if (*top_site == *current_site) {
   11543     // We install a dependency for pretenuring only on the outermost literal.
   11544     top_info()->dependencies()->AssumeTenuringDecision(top_site);
   11545   }
   11546   top_info()->dependencies()->AssumeTransitionStable(current_site);
   11547 
   11548   HInstruction* object =
   11549       Add<HAllocate>(object_size_constant, type, pretenure_flag, instance_type,
   11550                      graph()->GetConstant0(), top_site);
   11551 
   11552   // If allocation folding reaches kMaxRegularHeapObjectSize the
   11553   // elements array may not get folded into the object. Hence, we set the
   11554   // elements pointer to empty fixed array and let store elimination remove
   11555   // this store in the folding case.
   11556   HConstant* empty_fixed_array = Add<HConstant>(
   11557       isolate()->factory()->empty_fixed_array());
   11558   Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11559       empty_fixed_array);
   11560 
   11561   BuildEmitObjectHeader(boilerplate_object, object);
   11562 
   11563   // Similarly to the elements pointer, there is no guarantee that all
   11564   // property allocations can get folded, so pre-initialize all in-object
   11565   // properties to a safe value.
   11566   BuildInitializeInobjectProperties(object, initial_map);
   11567 
   11568   Handle<FixedArrayBase> elements(boilerplate_object->elements());
   11569   int elements_size = (elements->length() > 0 &&
   11570       elements->map() != isolate()->heap()->fixed_cow_array_map()) ?
   11571           elements->Size() : 0;
   11572 
   11573   if (pretenure_flag == TENURED &&
   11574       elements->map() == isolate()->heap()->fixed_cow_array_map() &&
   11575       isolate()->heap()->InNewSpace(*elements)) {
   11576     // If we would like to pretenure a fixed cow array, we must ensure that the
   11577     // array is already in old space, otherwise we'll create too many old-to-
   11578     // new-space pointers (overflowing the store buffer).
   11579     elements = Handle<FixedArrayBase>(
   11580         isolate()->factory()->CopyAndTenureFixedCOWArray(
   11581             Handle<FixedArray>::cast(elements)));
   11582     boilerplate_object->set_elements(*elements);
   11583   }
   11584 
   11585   HInstruction* object_elements = NULL;
   11586   if (elements_size > 0) {
   11587     HValue* object_elements_size = Add<HConstant>(elements_size);
   11588     InstanceType instance_type = boilerplate_object->HasFastDoubleElements()
   11589         ? FIXED_DOUBLE_ARRAY_TYPE : FIXED_ARRAY_TYPE;
   11590     object_elements = Add<HAllocate>(object_elements_size, HType::HeapObject(),
   11591                                      pretenure_flag, instance_type,
   11592                                      graph()->GetConstant0(), top_site);
   11593     BuildEmitElements(boilerplate_object, elements, object_elements,
   11594                       site_context);
   11595     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11596                           object_elements);
   11597   } else {
   11598     Handle<Object> elements_field =
   11599         Handle<Object>(boilerplate_object->elements(), isolate());
   11600     HInstruction* object_elements_cow = Add<HConstant>(elements_field);
   11601     Add<HStoreNamedField>(object, HObjectAccess::ForElementsPointer(),
   11602                           object_elements_cow);
   11603   }
   11604 
   11605   // Copy in-object properties.
   11606   if (initial_map->NumberOfFields() != 0 ||
   11607       initial_map->unused_property_fields() > 0) {
   11608     BuildEmitInObjectProperties(boilerplate_object, object, site_context,
   11609                                 pretenure_flag);
   11610   }
   11611   return object;
   11612 }
   11613 
   11614 
   11615 void HOptimizedGraphBuilder::BuildEmitObjectHeader(
   11616     Handle<JSObject> boilerplate_object,
   11617     HInstruction* object) {
   11618   DCHECK(boilerplate_object->properties()->length() == 0);
   11619 
   11620   Handle<Map> boilerplate_object_map(boilerplate_object->map());
   11621   AddStoreMapConstant(object, boilerplate_object_map);
   11622 
   11623   Handle<Object> properties_field =
   11624       Handle<Object>(boilerplate_object->properties(), isolate());
   11625   DCHECK(*properties_field == isolate()->heap()->empty_fixed_array());
   11626   HInstruction* properties = Add<HConstant>(properties_field);
   11627   HObjectAccess access = HObjectAccess::ForPropertiesPointer();
   11628   Add<HStoreNamedField>(object, access, properties);
   11629 
   11630   if (boilerplate_object->IsJSArray()) {
   11631     Handle<JSArray> boilerplate_array =
   11632         Handle<JSArray>::cast(boilerplate_object);
   11633     Handle<Object> length_field =
   11634         Handle<Object>(boilerplate_array->length(), isolate());
   11635     HInstruction* length = Add<HConstant>(length_field);
   11636 
   11637     DCHECK(boilerplate_array->length()->IsSmi());
   11638     Add<HStoreNamedField>(object, HObjectAccess::ForArrayLength(
   11639         boilerplate_array->GetElementsKind()), length);
   11640   }
   11641 }
   11642 
   11643 
   11644 void HOptimizedGraphBuilder::BuildEmitInObjectProperties(
   11645     Handle<JSObject> boilerplate_object,
   11646     HInstruction* object,
   11647     AllocationSiteUsageContext* site_context,
   11648     PretenureFlag pretenure_flag) {
   11649   Handle<Map> boilerplate_map(boilerplate_object->map());
   11650   Handle<DescriptorArray> descriptors(boilerplate_map->instance_descriptors());
   11651   int limit = boilerplate_map->NumberOfOwnDescriptors();
   11652 
   11653   int copied_fields = 0;
   11654   for (int i = 0; i < limit; i++) {
   11655     PropertyDetails details = descriptors->GetDetails(i);
   11656     if (details.type() != DATA) continue;
   11657     copied_fields++;
   11658     FieldIndex field_index = FieldIndex::ForDescriptor(*boilerplate_map, i);
   11659 
   11660 
   11661     int property_offset = field_index.offset();
   11662     Handle<Name> name(descriptors->GetKey(i));
   11663 
   11664     // The access for the store depends on the type of the boilerplate.
   11665     HObjectAccess access = boilerplate_object->IsJSArray() ?
   11666         HObjectAccess::ForJSArrayOffset(property_offset) :
   11667         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
   11668 
   11669     if (boilerplate_object->IsUnboxedDoubleField(field_index)) {
   11670       CHECK(!boilerplate_object->IsJSArray());
   11671       double value = boilerplate_object->RawFastDoublePropertyAt(field_index);
   11672       access = access.WithRepresentation(Representation::Double());
   11673       Add<HStoreNamedField>(object, access, Add<HConstant>(value));
   11674       continue;
   11675     }
   11676     Handle<Object> value(boilerplate_object->RawFastPropertyAt(field_index),
   11677                          isolate());
   11678 
   11679     if (value->IsJSObject()) {
   11680       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   11681       Handle<AllocationSite> current_site = site_context->EnterNewScope();
   11682       HInstruction* result =
   11683           BuildFastLiteral(value_object, site_context);
   11684       site_context->ExitScope(current_site, value_object);
   11685       Add<HStoreNamedField>(object, access, result);
   11686     } else {
   11687       Representation representation = details.representation();
   11688       HInstruction* value_instruction;
   11689 
   11690       if (representation.IsDouble()) {
   11691         // Allocate a HeapNumber box and store the value into it.
   11692         HValue* heap_number_constant = Add<HConstant>(HeapNumber::kSize);
   11693         HInstruction* double_box = Add<HAllocate>(
   11694             heap_number_constant, HType::HeapObject(), pretenure_flag,
   11695             MUTABLE_HEAP_NUMBER_TYPE, graph()->GetConstant0());
   11696         AddStoreMapConstant(double_box,
   11697             isolate()->factory()->mutable_heap_number_map());
   11698         // Unwrap the mutable heap number from the boilerplate.
   11699         HValue* double_value =
   11700             Add<HConstant>(Handle<HeapNumber>::cast(value)->value());
   11701         Add<HStoreNamedField>(
   11702             double_box, HObjectAccess::ForHeapNumberValue(), double_value);
   11703         value_instruction = double_box;
   11704       } else if (representation.IsSmi()) {
   11705         value_instruction = value->IsUninitialized(isolate())
   11706                                 ? graph()->GetConstant0()
   11707                                 : Add<HConstant>(value);
   11708         // Ensure that value is stored as smi.
   11709         access = access.WithRepresentation(representation);
   11710       } else {
   11711         value_instruction = Add<HConstant>(value);
   11712       }
   11713 
   11714       Add<HStoreNamedField>(object, access, value_instruction);
   11715     }
   11716   }
   11717 
   11718   int inobject_properties = boilerplate_object->map()->GetInObjectProperties();
   11719   HInstruction* value_instruction =
   11720       Add<HConstant>(isolate()->factory()->one_pointer_filler_map());
   11721   for (int i = copied_fields; i < inobject_properties; i++) {
   11722     DCHECK(boilerplate_object->IsJSObject());
   11723     int property_offset = boilerplate_object->GetInObjectPropertyOffset(i);
   11724     HObjectAccess access =
   11725         HObjectAccess::ForMapAndOffset(boilerplate_map, property_offset);
   11726     Add<HStoreNamedField>(object, access, value_instruction);
   11727   }
   11728 }
   11729 
   11730 
   11731 void HOptimizedGraphBuilder::BuildEmitElements(
   11732     Handle<JSObject> boilerplate_object,
   11733     Handle<FixedArrayBase> elements,
   11734     HValue* object_elements,
   11735     AllocationSiteUsageContext* site_context) {
   11736   ElementsKind kind = boilerplate_object->map()->elements_kind();
   11737   int elements_length = elements->length();
   11738   HValue* object_elements_length = Add<HConstant>(elements_length);
   11739   BuildInitializeElementsHeader(object_elements, kind, object_elements_length);
   11740 
   11741   // Copy elements backing store content.
   11742   if (elements->IsFixedDoubleArray()) {
   11743     BuildEmitFixedDoubleArray(elements, kind, object_elements);
   11744   } else if (elements->IsFixedArray()) {
   11745     BuildEmitFixedArray(elements, kind, object_elements,
   11746                         site_context);
   11747   } else {
   11748     UNREACHABLE();
   11749   }
   11750 }
   11751 
   11752 
   11753 void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
   11754     Handle<FixedArrayBase> elements,
   11755     ElementsKind kind,
   11756     HValue* object_elements) {
   11757   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   11758   int elements_length = elements->length();
   11759   for (int i = 0; i < elements_length; i++) {
   11760     HValue* key_constant = Add<HConstant>(i);
   11761     HInstruction* value_instruction =
   11762         Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
   11763                         kind, ALLOW_RETURN_HOLE);
   11764     HInstruction* store = Add<HStoreKeyed>(object_elements, key_constant,
   11765                                            value_instruction, nullptr, kind);
   11766     store->SetFlag(HValue::kTruncatingToNumber);
   11767   }
   11768 }
   11769 
   11770 
   11771 void HOptimizedGraphBuilder::BuildEmitFixedArray(
   11772     Handle<FixedArrayBase> elements,
   11773     ElementsKind kind,
   11774     HValue* object_elements,
   11775     AllocationSiteUsageContext* site_context) {
   11776   HInstruction* boilerplate_elements = Add<HConstant>(elements);
   11777   int elements_length = elements->length();
   11778   Handle<FixedArray> fast_elements = Handle<FixedArray>::cast(elements);
   11779   for (int i = 0; i < elements_length; i++) {
   11780     Handle<Object> value(fast_elements->get(i), isolate());
   11781     HValue* key_constant = Add<HConstant>(i);
   11782     if (value->IsJSObject()) {
   11783       Handle<JSObject> value_object = Handle<JSObject>::cast(value);
   11784       Handle<AllocationSite> current_site = site_context->EnterNewScope();
   11785       HInstruction* result =
   11786           BuildFastLiteral(value_object, site_context);
   11787       site_context->ExitScope(current_site, value_object);
   11788       Add<HStoreKeyed>(object_elements, key_constant, result, nullptr, kind);
   11789     } else {
   11790       ElementsKind copy_kind =
   11791           kind == FAST_HOLEY_SMI_ELEMENTS ? FAST_HOLEY_ELEMENTS : kind;
   11792       HInstruction* value_instruction =
   11793           Add<HLoadKeyed>(boilerplate_elements, key_constant, nullptr, nullptr,
   11794                           copy_kind, ALLOW_RETURN_HOLE);
   11795       Add<HStoreKeyed>(object_elements, key_constant, value_instruction,
   11796                        nullptr, copy_kind);
   11797     }
   11798   }
   11799 }
   11800 
   11801 
   11802 void HOptimizedGraphBuilder::VisitThisFunction(ThisFunction* expr) {
   11803   DCHECK(!HasStackOverflow());
   11804   DCHECK(current_block() != NULL);
   11805   DCHECK(current_block()->HasPredecessor());
   11806   HInstruction* instr = BuildThisFunction();
   11807   return ast_context()->ReturnInstruction(instr, expr->id());
   11808 }
   11809 
   11810 
   11811 void HOptimizedGraphBuilder::VisitSuperPropertyReference(
   11812     SuperPropertyReference* expr) {
   11813   DCHECK(!HasStackOverflow());
   11814   DCHECK(current_block() != NULL);
   11815   DCHECK(current_block()->HasPredecessor());
   11816   return Bailout(kSuperReference);
   11817 }
   11818 
   11819 
   11820 void HOptimizedGraphBuilder::VisitSuperCallReference(SuperCallReference* expr) {
   11821   DCHECK(!HasStackOverflow());
   11822   DCHECK(current_block() != NULL);
   11823   DCHECK(current_block()->HasPredecessor());
   11824   return Bailout(kSuperReference);
   11825 }
   11826 
   11827 void HOptimizedGraphBuilder::VisitDeclarations(
   11828     Declaration::List* declarations) {
   11829   DCHECK(globals_.is_empty());
   11830   AstVisitor<HOptimizedGraphBuilder>::VisitDeclarations(declarations);
   11831   if (!globals_.is_empty()) {
   11832     Handle<FixedArray> array =
   11833        isolate()->factory()->NewFixedArray(globals_.length(), TENURED);
   11834     for (int i = 0; i < globals_.length(); ++i) array->set(i, *globals_.at(i));
   11835     int flags = current_info()->GetDeclareGlobalsFlags();
   11836     Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate());
   11837     Add<HDeclareGlobals>(array, flags, vector);
   11838     globals_.Rewind(0);
   11839   }
   11840 }
   11841 
   11842 
   11843 void HOptimizedGraphBuilder::VisitVariableDeclaration(
   11844     VariableDeclaration* declaration) {
   11845   VariableProxy* proxy = declaration->proxy();
   11846   Variable* variable = proxy->var();
   11847   switch (variable->location()) {
   11848     case VariableLocation::UNALLOCATED: {
   11849       DCHECK(!variable->binding_needs_init());
   11850       FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
   11851       DCHECK(!slot.IsInvalid());
   11852       globals_.Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
   11853       globals_.Add(isolate()->factory()->undefined_value(), zone());
   11854       return;
   11855     }
   11856     case VariableLocation::PARAMETER:
   11857     case VariableLocation::LOCAL:
   11858       if (variable->binding_needs_init()) {
   11859         HValue* value = graph()->GetConstantHole();
   11860         environment()->Bind(variable, value);
   11861       }
   11862       break;
   11863     case VariableLocation::CONTEXT:
   11864       if (variable->binding_needs_init()) {
   11865         HValue* value = graph()->GetConstantHole();
   11866         HValue* context = environment()->context();
   11867         HStoreContextSlot* store = Add<HStoreContextSlot>(
   11868             context, variable->index(), HStoreContextSlot::kNoCheck, value);
   11869         if (store->HasObservableSideEffects()) {
   11870           Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
   11871         }
   11872       }
   11873       break;
   11874     case VariableLocation::LOOKUP:
   11875       return Bailout(kUnsupportedLookupSlotInDeclaration);
   11876     case VariableLocation::MODULE:
   11877       UNREACHABLE();
   11878   }
   11879 }
   11880 
   11881 
   11882 void HOptimizedGraphBuilder::VisitFunctionDeclaration(
   11883     FunctionDeclaration* declaration) {
   11884   VariableProxy* proxy = declaration->proxy();
   11885   Variable* variable = proxy->var();
   11886   switch (variable->location()) {
   11887     case VariableLocation::UNALLOCATED: {
   11888       FeedbackVectorSlot slot = proxy->VariableFeedbackSlot();
   11889       DCHECK(!slot.IsInvalid());
   11890       globals_.Add(handle(Smi::FromInt(slot.ToInt()), isolate()), zone());
   11891       Handle<SharedFunctionInfo> function = Compiler::GetSharedFunctionInfo(
   11892           declaration->fun(), current_info()->script(), top_info());
   11893       // Check for stack-overflow exception.
   11894       if (function.is_null()) return SetStackOverflow();
   11895       globals_.Add(function, zone());
   11896       return;
   11897     }
   11898     case VariableLocation::PARAMETER:
   11899     case VariableLocation::LOCAL: {
   11900       CHECK_ALIVE(VisitForValue(declaration->fun()));
   11901       HValue* value = Pop();
   11902       BindIfLive(variable, value);
   11903       break;
   11904     }
   11905     case VariableLocation::CONTEXT: {
   11906       CHECK_ALIVE(VisitForValue(declaration->fun()));
   11907       HValue* value = Pop();
   11908       HValue* context = environment()->context();
   11909       HStoreContextSlot* store = Add<HStoreContextSlot>(
   11910           context, variable->index(), HStoreContextSlot::kNoCheck, value);
   11911       if (store->HasObservableSideEffects()) {
   11912         Add<HSimulate>(proxy->id(), REMOVABLE_SIMULATE);
   11913       }
   11914       break;
   11915     }
   11916     case VariableLocation::LOOKUP:
   11917       return Bailout(kUnsupportedLookupSlotInDeclaration);
   11918     case VariableLocation::MODULE:
   11919       UNREACHABLE();
   11920   }
   11921 }
   11922 
   11923 
   11924 void HOptimizedGraphBuilder::VisitRewritableExpression(
   11925     RewritableExpression* node) {
   11926   CHECK_ALIVE(Visit(node->expression()));
   11927 }
   11928 
   11929 
   11930 // Generators for inline runtime functions.
   11931 // Support for types.
   11932 void HOptimizedGraphBuilder::GenerateIsSmi(CallRuntime* call) {
   11933   DCHECK(call->arguments()->length() == 1);
   11934   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11935   HValue* value = Pop();
   11936   HIsSmiAndBranch* result = New<HIsSmiAndBranch>(value);
   11937   return ast_context()->ReturnControl(result, call->id());
   11938 }
   11939 
   11940 
   11941 void HOptimizedGraphBuilder::GenerateIsJSReceiver(CallRuntime* call) {
   11942   DCHECK(call->arguments()->length() == 1);
   11943   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11944   HValue* value = Pop();
   11945   HHasInstanceTypeAndBranch* result =
   11946       New<HHasInstanceTypeAndBranch>(value,
   11947                                      FIRST_JS_RECEIVER_TYPE,
   11948                                      LAST_JS_RECEIVER_TYPE);
   11949   return ast_context()->ReturnControl(result, call->id());
   11950 }
   11951 
   11952 void HOptimizedGraphBuilder::GenerateIsArray(CallRuntime* call) {
   11953   DCHECK(call->arguments()->length() == 1);
   11954   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11955   HValue* value = Pop();
   11956   HHasInstanceTypeAndBranch* result =
   11957       New<HHasInstanceTypeAndBranch>(value, JS_ARRAY_TYPE);
   11958   return ast_context()->ReturnControl(result, call->id());
   11959 }
   11960 
   11961 
   11962 void HOptimizedGraphBuilder::GenerateIsTypedArray(CallRuntime* call) {
   11963   DCHECK(call->arguments()->length() == 1);
   11964   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11965   HValue* value = Pop();
   11966   HHasInstanceTypeAndBranch* result =
   11967       New<HHasInstanceTypeAndBranch>(value, JS_TYPED_ARRAY_TYPE);
   11968   return ast_context()->ReturnControl(result, call->id());
   11969 }
   11970 
   11971 
   11972 void HOptimizedGraphBuilder::GenerateIsRegExp(CallRuntime* call) {
   11973   DCHECK(call->arguments()->length() == 1);
   11974   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11975   HValue* value = Pop();
   11976   HHasInstanceTypeAndBranch* result =
   11977       New<HHasInstanceTypeAndBranch>(value, JS_REGEXP_TYPE);
   11978   return ast_context()->ReturnControl(result, call->id());
   11979 }
   11980 
   11981 
   11982 void HOptimizedGraphBuilder::GenerateToInteger(CallRuntime* call) {
   11983   DCHECK_EQ(1, call->arguments()->length());
   11984   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   11985   HValue* input = Pop();
   11986   if (input->type().IsSmi()) {
   11987     return ast_context()->ReturnValue(input);
   11988   } else {
   11989     Callable callable = CodeFactory::ToInteger(isolate());
   11990     HValue* stub = Add<HConstant>(callable.code());
   11991     HValue* values[] = {input};
   11992     HInstruction* result = New<HCallWithDescriptor>(
   11993         stub, 0, callable.descriptor(), ArrayVector(values));
   11994     return ast_context()->ReturnInstruction(result, call->id());
   11995   }
   11996 }
   11997 
   11998 
   11999 void HOptimizedGraphBuilder::GenerateToObject(CallRuntime* call) {
   12000   DCHECK_EQ(1, call->arguments()->length());
   12001   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12002   HValue* value = Pop();
   12003   HValue* result = BuildToObject(value);
   12004   return ast_context()->ReturnValue(result);
   12005 }
   12006 
   12007 
   12008 void HOptimizedGraphBuilder::GenerateToString(CallRuntime* call) {
   12009   DCHECK_EQ(1, call->arguments()->length());
   12010   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12011   HValue* input = Pop();
   12012   if (input->type().IsString()) {
   12013     return ast_context()->ReturnValue(input);
   12014   } else {
   12015     Callable callable = CodeFactory::ToString(isolate());
   12016     HValue* stub = Add<HConstant>(callable.code());
   12017     HValue* values[] = {input};
   12018     HInstruction* result = New<HCallWithDescriptor>(
   12019         stub, 0, callable.descriptor(), ArrayVector(values));
   12020     return ast_context()->ReturnInstruction(result, call->id());
   12021   }
   12022 }
   12023 
   12024 
   12025 void HOptimizedGraphBuilder::GenerateToLength(CallRuntime* call) {
   12026   DCHECK_EQ(1, call->arguments()->length());
   12027   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12028   Callable callable = CodeFactory::ToLength(isolate());
   12029   HValue* input = Pop();
   12030   HValue* stub = Add<HConstant>(callable.code());
   12031   HValue* values[] = {input};
   12032   HInstruction* result = New<HCallWithDescriptor>(
   12033       stub, 0, callable.descriptor(), ArrayVector(values));
   12034   return ast_context()->ReturnInstruction(result, call->id());
   12035 }
   12036 
   12037 
   12038 void HOptimizedGraphBuilder::GenerateToNumber(CallRuntime* call) {
   12039   DCHECK_EQ(1, call->arguments()->length());
   12040   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12041   Callable callable = CodeFactory::ToNumber(isolate());
   12042   HValue* input = Pop();
   12043   HValue* result = BuildToNumber(input);
   12044   if (result->HasObservableSideEffects()) {
   12045     if (!ast_context()->IsEffect()) Push(result);
   12046     Add<HSimulate>(call->id(), REMOVABLE_SIMULATE);
   12047     if (!ast_context()->IsEffect()) result = Pop();
   12048   }
   12049   return ast_context()->ReturnValue(result);
   12050 }
   12051 
   12052 
   12053 void HOptimizedGraphBuilder::GenerateIsJSProxy(CallRuntime* call) {
   12054   DCHECK(call->arguments()->length() == 1);
   12055   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12056   HValue* value = Pop();
   12057   HIfContinuation continuation;
   12058   IfBuilder if_proxy(this);
   12059 
   12060   HValue* smicheck = if_proxy.IfNot<HIsSmiAndBranch>(value);
   12061   if_proxy.And();
   12062   HValue* map = Add<HLoadNamedField>(value, smicheck, HObjectAccess::ForMap());
   12063   HValue* instance_type =
   12064       Add<HLoadNamedField>(map, nullptr, HObjectAccess::ForMapInstanceType());
   12065   if_proxy.If<HCompareNumericAndBranch>(
   12066       instance_type, Add<HConstant>(JS_PROXY_TYPE), Token::EQ);
   12067 
   12068   if_proxy.CaptureContinuation(&continuation);
   12069   return ast_context()->ReturnContinuation(&continuation, call->id());
   12070 }
   12071 
   12072 
   12073 void HOptimizedGraphBuilder::GenerateHasFastPackedElements(CallRuntime* call) {
   12074   DCHECK(call->arguments()->length() == 1);
   12075   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12076   HValue* object = Pop();
   12077   HIfContinuation continuation(graph()->CreateBasicBlock(),
   12078                                graph()->CreateBasicBlock());
   12079   IfBuilder if_not_smi(this);
   12080   if_not_smi.IfNot<HIsSmiAndBranch>(object);
   12081   if_not_smi.Then();
   12082   {
   12083     NoObservableSideEffectsScope no_effects(this);
   12084 
   12085     IfBuilder if_fast_packed(this);
   12086     HValue* elements_kind = BuildGetElementsKind(object);
   12087     if_fast_packed.If<HCompareNumericAndBranch>(
   12088         elements_kind, Add<HConstant>(FAST_SMI_ELEMENTS), Token::EQ);
   12089     if_fast_packed.Or();
   12090     if_fast_packed.If<HCompareNumericAndBranch>(
   12091         elements_kind, Add<HConstant>(FAST_ELEMENTS), Token::EQ);
   12092     if_fast_packed.Or();
   12093     if_fast_packed.If<HCompareNumericAndBranch>(
   12094         elements_kind, Add<HConstant>(FAST_DOUBLE_ELEMENTS), Token::EQ);
   12095     if_fast_packed.JoinContinuation(&continuation);
   12096   }
   12097   if_not_smi.JoinContinuation(&continuation);
   12098   return ast_context()->ReturnContinuation(&continuation, call->id());
   12099 }
   12100 
   12101 
   12102 // Fast support for charCodeAt(n).
   12103 void HOptimizedGraphBuilder::GenerateStringCharCodeAt(CallRuntime* call) {
   12104   DCHECK(call->arguments()->length() == 2);
   12105   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12106   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12107   HValue* index = Pop();
   12108   HValue* string = Pop();
   12109   HInstruction* result = BuildStringCharCodeAt(string, index);
   12110   return ast_context()->ReturnInstruction(result, call->id());
   12111 }
   12112 
   12113 
   12114 // Fast support for SubString.
   12115 void HOptimizedGraphBuilder::GenerateSubString(CallRuntime* call) {
   12116   DCHECK_EQ(3, call->arguments()->length());
   12117   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12118   Callable callable = CodeFactory::SubString(isolate());
   12119   HValue* stub = Add<HConstant>(callable.code());
   12120   HValue* to = Pop();
   12121   HValue* from = Pop();
   12122   HValue* string = Pop();
   12123   HValue* values[] = {string, from, to};
   12124   HInstruction* result = New<HCallWithDescriptor>(
   12125       stub, 0, callable.descriptor(), ArrayVector(values));
   12126   result->set_type(HType::String());
   12127   return ast_context()->ReturnInstruction(result, call->id());
   12128 }
   12129 
   12130 // Support for direct creation of new objects.
   12131 void HOptimizedGraphBuilder::GenerateNewObject(CallRuntime* call) {
   12132   DCHECK_EQ(2, call->arguments()->length());
   12133   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12134   FastNewObjectStub stub(isolate());
   12135   FastNewObjectDescriptor descriptor(isolate());
   12136   HValue* values[] = {Pop(), Pop()};
   12137   HConstant* stub_value = Add<HConstant>(stub.GetCode());
   12138   HInstruction* result =
   12139       New<HCallWithDescriptor>(stub_value, 0, descriptor, ArrayVector(values));
   12140   return ast_context()->ReturnInstruction(result, call->id());
   12141 }
   12142 
   12143 // Support for direct calls from JavaScript to native RegExp code.
   12144 void HOptimizedGraphBuilder::GenerateRegExpExec(CallRuntime* call) {
   12145   DCHECK_EQ(4, call->arguments()->length());
   12146   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12147   Callable callable = CodeFactory::RegExpExec(isolate());
   12148   HValue* last_match_info = Pop();
   12149   HValue* index = Pop();
   12150   HValue* subject = Pop();
   12151   HValue* regexp_object = Pop();
   12152   HValue* stub = Add<HConstant>(callable.code());
   12153   HValue* values[] = {regexp_object, subject, index, last_match_info};
   12154   HInstruction* result = New<HCallWithDescriptor>(
   12155       stub, 0, callable.descriptor(), ArrayVector(values));
   12156   return ast_context()->ReturnInstruction(result, call->id());
   12157 }
   12158 
   12159 
   12160 // Fast support for number to string.
   12161 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) {
   12162   DCHECK_EQ(1, call->arguments()->length());
   12163   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12164   HValue* number = Pop();
   12165   HValue* result = BuildNumberToString(number, AstType::Any());
   12166   return ast_context()->ReturnValue(result);
   12167 }
   12168 
   12169 
   12170 // Fast support for calls.
   12171 void HOptimizedGraphBuilder::GenerateCall(CallRuntime* call) {
   12172   DCHECK_LE(2, call->arguments()->length());
   12173   CHECK_ALIVE(VisitExpressions(call->arguments()));
   12174   CallTrampolineDescriptor descriptor(isolate());
   12175   PushArgumentsFromEnvironment(call->arguments()->length() - 1);
   12176   HValue* trampoline = Add<HConstant>(isolate()->builtins()->Call());
   12177   HValue* target = Pop();
   12178   HValue* values[] = {target, Add<HConstant>(call->arguments()->length() - 2)};
   12179   HInstruction* result =
   12180       New<HCallWithDescriptor>(trampoline, call->arguments()->length() - 1,
   12181                                descriptor, ArrayVector(values));
   12182   return ast_context()->ReturnInstruction(result, call->id());
   12183 }
   12184 
   12185 
   12186 void HOptimizedGraphBuilder::GenerateFixedArrayGet(CallRuntime* call) {
   12187   DCHECK(call->arguments()->length() == 2);
   12188   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12189   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12190   HValue* index = Pop();
   12191   HValue* object = Pop();
   12192   HInstruction* result = New<HLoadKeyed>(
   12193       object, index, nullptr, nullptr, FAST_HOLEY_ELEMENTS, ALLOW_RETURN_HOLE);
   12194   return ast_context()->ReturnInstruction(result, call->id());
   12195 }
   12196 
   12197 
   12198 void HOptimizedGraphBuilder::GenerateFixedArraySet(CallRuntime* call) {
   12199   DCHECK(call->arguments()->length() == 3);
   12200   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12201   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12202   CHECK_ALIVE(VisitForValue(call->arguments()->at(2)));
   12203   HValue* value = Pop();
   12204   HValue* index = Pop();
   12205   HValue* object = Pop();
   12206   NoObservableSideEffectsScope no_effects(this);
   12207   Add<HStoreKeyed>(object, index, value, nullptr, FAST_HOLEY_ELEMENTS);
   12208   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12209 }
   12210 
   12211 
   12212 void HOptimizedGraphBuilder::GenerateTheHole(CallRuntime* call) {
   12213   DCHECK(call->arguments()->length() == 0);
   12214   return ast_context()->ReturnValue(graph()->GetConstantHole());
   12215 }
   12216 
   12217 
   12218 void HOptimizedGraphBuilder::GenerateCreateIterResultObject(CallRuntime* call) {
   12219   DCHECK_EQ(2, call->arguments()->length());
   12220   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12221   CHECK_ALIVE(VisitForValue(call->arguments()->at(1)));
   12222   HValue* done = Pop();
   12223   HValue* value = Pop();
   12224   HValue* result = BuildCreateIterResultObject(value, done);
   12225   return ast_context()->ReturnValue(result);
   12226 }
   12227 
   12228 
   12229 void HOptimizedGraphBuilder::GenerateJSCollectionGetTable(CallRuntime* call) {
   12230   DCHECK(call->arguments()->length() == 1);
   12231   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12232   HValue* receiver = Pop();
   12233   HInstruction* result = New<HLoadNamedField>(
   12234       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
   12235   return ast_context()->ReturnInstruction(result, call->id());
   12236 }
   12237 
   12238 
   12239 void HOptimizedGraphBuilder::GenerateStringGetRawHashField(CallRuntime* call) {
   12240   DCHECK(call->arguments()->length() == 1);
   12241   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12242   HValue* object = Pop();
   12243   HInstruction* result = New<HLoadNamedField>(
   12244       object, nullptr, HObjectAccess::ForStringHashField());
   12245   return ast_context()->ReturnInstruction(result, call->id());
   12246 }
   12247 
   12248 
   12249 template <typename CollectionType>
   12250 HValue* HOptimizedGraphBuilder::BuildAllocateOrderedHashTable() {
   12251   static const int kCapacity = CollectionType::kMinCapacity;
   12252   static const int kBucketCount = kCapacity / CollectionType::kLoadFactor;
   12253   static const int kFixedArrayLength = CollectionType::kHashTableStartIndex +
   12254                                        kBucketCount +
   12255                                        (kCapacity * CollectionType::kEntrySize);
   12256   static const int kSizeInBytes =
   12257       FixedArray::kHeaderSize + (kFixedArrayLength * kPointerSize);
   12258 
   12259   // Allocate the table and add the proper map.
   12260   HValue* table =
   12261       Add<HAllocate>(Add<HConstant>(kSizeInBytes), HType::HeapObject(),
   12262                      NOT_TENURED, FIXED_ARRAY_TYPE, graph()->GetConstant0());
   12263   AddStoreMapConstant(table, isolate()->factory()->ordered_hash_table_map());
   12264 
   12265   // Initialize the FixedArray...
   12266   HValue* length = Add<HConstant>(kFixedArrayLength);
   12267   Add<HStoreNamedField>(table, HObjectAccess::ForFixedArrayLength(), length);
   12268 
   12269   // ...and the OrderedHashTable fields.
   12270   Add<HStoreNamedField>(
   12271       table,
   12272       HObjectAccess::ForOrderedHashTableNumberOfBuckets<CollectionType>(),
   12273       Add<HConstant>(kBucketCount));
   12274   Add<HStoreNamedField>(
   12275       table,
   12276       HObjectAccess::ForOrderedHashTableNumberOfElements<CollectionType>(),
   12277       graph()->GetConstant0());
   12278   Add<HStoreNamedField>(
   12279       table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
   12280                  CollectionType>(),
   12281       graph()->GetConstant0());
   12282 
   12283   // Fill the buckets with kNotFound.
   12284   HValue* not_found = Add<HConstant>(CollectionType::kNotFound);
   12285   for (int i = 0; i < kBucketCount; ++i) {
   12286     Add<HStoreNamedField>(
   12287         table, HObjectAccess::ForOrderedHashTableBucket<CollectionType>(i),
   12288         not_found);
   12289   }
   12290 
   12291   // Fill the data table with undefined.
   12292   HValue* undefined = graph()->GetConstantUndefined();
   12293   for (int i = 0; i < (kCapacity * CollectionType::kEntrySize); ++i) {
   12294     Add<HStoreNamedField>(table,
   12295                           HObjectAccess::ForOrderedHashTableDataTableIndex<
   12296                               CollectionType, kBucketCount>(i),
   12297                           undefined);
   12298   }
   12299 
   12300   return table;
   12301 }
   12302 
   12303 
   12304 void HOptimizedGraphBuilder::GenerateSetInitialize(CallRuntime* call) {
   12305   DCHECK(call->arguments()->length() == 1);
   12306   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12307   HValue* receiver = Pop();
   12308 
   12309   NoObservableSideEffectsScope no_effects(this);
   12310   HValue* table = BuildAllocateOrderedHashTable<OrderedHashSet>();
   12311   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
   12312   return ast_context()->ReturnValue(receiver);
   12313 }
   12314 
   12315 
   12316 void HOptimizedGraphBuilder::GenerateMapInitialize(CallRuntime* call) {
   12317   DCHECK(call->arguments()->length() == 1);
   12318   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12319   HValue* receiver = Pop();
   12320 
   12321   NoObservableSideEffectsScope no_effects(this);
   12322   HValue* table = BuildAllocateOrderedHashTable<OrderedHashMap>();
   12323   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(), table);
   12324   return ast_context()->ReturnValue(receiver);
   12325 }
   12326 
   12327 
   12328 template <typename CollectionType>
   12329 void HOptimizedGraphBuilder::BuildOrderedHashTableClear(HValue* receiver) {
   12330   HValue* old_table = Add<HLoadNamedField>(
   12331       receiver, nullptr, HObjectAccess::ForJSCollectionTable());
   12332   HValue* new_table = BuildAllocateOrderedHashTable<CollectionType>();
   12333   Add<HStoreNamedField>(
   12334       old_table, HObjectAccess::ForOrderedHashTableNextTable<CollectionType>(),
   12335       new_table);
   12336   Add<HStoreNamedField>(
   12337       old_table, HObjectAccess::ForOrderedHashTableNumberOfDeletedElements<
   12338                      CollectionType>(),
   12339       Add<HConstant>(CollectionType::kClearedTableSentinel));
   12340   Add<HStoreNamedField>(receiver, HObjectAccess::ForJSCollectionTable(),
   12341                         new_table);
   12342 }
   12343 
   12344 
   12345 void HOptimizedGraphBuilder::GenerateSetClear(CallRuntime* call) {
   12346   DCHECK(call->arguments()->length() == 1);
   12347   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12348   HValue* receiver = Pop();
   12349 
   12350   NoObservableSideEffectsScope no_effects(this);
   12351   BuildOrderedHashTableClear<OrderedHashSet>(receiver);
   12352   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12353 }
   12354 
   12355 
   12356 void HOptimizedGraphBuilder::GenerateMapClear(CallRuntime* call) {
   12357   DCHECK(call->arguments()->length() == 1);
   12358   CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
   12359   HValue* receiver = Pop();
   12360 
   12361   NoObservableSideEffectsScope no_effects(this);
   12362   BuildOrderedHashTableClear<OrderedHashMap>(receiver);
   12363   return ast_context()->ReturnValue(graph()->GetConstantUndefined());
   12364 }
   12365 
   12366 void HOptimizedGraphBuilder::GenerateDebugBreakInOptimizedCode(
   12367     CallRuntime* call) {
   12368   Add<HDebugBreak>();
   12369   return ast_context()->ReturnValue(graph()->GetConstant0());
   12370 }
   12371 
   12372 
   12373 void HOptimizedGraphBuilder::GenerateDebugIsActive(CallRuntime* call) {
   12374   DCHECK(call->arguments()->length() == 0);
   12375   HValue* ref =
   12376       Add<HConstant>(ExternalReference::debug_is_active_address(isolate()));
   12377   HValue* value =
   12378       Add<HLoadNamedField>(ref, nullptr, HObjectAccess::ForExternalUInteger8());
   12379   return ast_context()->ReturnValue(value);
   12380 }
   12381 
   12382 #undef CHECK_BAILOUT
   12383 #undef CHECK_ALIVE
   12384 
   12385 
   12386 HEnvironment::HEnvironment(HEnvironment* outer,
   12387                            Scope* scope,
   12388                            Handle<JSFunction> closure,
   12389                            Zone* zone)
   12390     : closure_(closure),
   12391       values_(0, zone),
   12392       frame_type_(JS_FUNCTION),
   12393       parameter_count_(0),
   12394       specials_count_(1),
   12395       local_count_(0),
   12396       outer_(outer),
   12397       entry_(NULL),
   12398       pop_count_(0),
   12399       push_count_(0),
   12400       ast_id_(BailoutId::None()),
   12401       zone_(zone) {
   12402   DeclarationScope* declaration_scope = scope->GetDeclarationScope();
   12403   Initialize(declaration_scope->num_parameters() + 1,
   12404              declaration_scope->num_stack_slots(), 0);
   12405 }
   12406 
   12407 
   12408 HEnvironment::HEnvironment(Zone* zone, int parameter_count)
   12409     : values_(0, zone),
   12410       frame_type_(STUB),
   12411       parameter_count_(parameter_count),
   12412       specials_count_(1),
   12413       local_count_(0),
   12414       outer_(NULL),
   12415       entry_(NULL),
   12416       pop_count_(0),
   12417       push_count_(0),
   12418       ast_id_(BailoutId::None()),
   12419       zone_(zone) {
   12420   Initialize(parameter_count, 0, 0);
   12421 }
   12422 
   12423 
   12424 HEnvironment::HEnvironment(const HEnvironment* other, Zone* zone)
   12425     : values_(0, zone),
   12426       frame_type_(JS_FUNCTION),
   12427       parameter_count_(0),
   12428       specials_count_(0),
   12429       local_count_(0),
   12430       outer_(NULL),
   12431       entry_(NULL),
   12432       pop_count_(0),
   12433       push_count_(0),
   12434       ast_id_(other->ast_id()),
   12435       zone_(zone) {
   12436   Initialize(other);
   12437 }
   12438 
   12439 
   12440 HEnvironment::HEnvironment(HEnvironment* outer,
   12441                            Handle<JSFunction> closure,
   12442                            FrameType frame_type,
   12443                            int arguments,
   12444                            Zone* zone)
   12445     : closure_(closure),
   12446       values_(arguments, zone),
   12447       frame_type_(frame_type),
   12448       parameter_count_(arguments),
   12449       specials_count_(0),
   12450       local_count_(0),
   12451       outer_(outer),
   12452       entry_(NULL),
   12453       pop_count_(0),
   12454       push_count_(0),
   12455       ast_id_(BailoutId::None()),
   12456       zone_(zone) {
   12457 }
   12458 
   12459 
   12460 void HEnvironment::Initialize(int parameter_count,
   12461                               int local_count,
   12462                               int stack_height) {
   12463   parameter_count_ = parameter_count;
   12464   local_count_ = local_count;
   12465 
   12466   // Avoid reallocating the temporaries' backing store on the first Push.
   12467   int total = parameter_count + specials_count_ + local_count + stack_height;
   12468   values_.Initialize(total + 4, zone());
   12469   for (int i = 0; i < total; ++i) values_.Add(NULL, zone());
   12470 }
   12471 
   12472 
   12473 void HEnvironment::Initialize(const HEnvironment* other) {
   12474   closure_ = other->closure();
   12475   values_.AddAll(other->values_, zone());
   12476   assigned_variables_.Union(other->assigned_variables_, zone());
   12477   frame_type_ = other->frame_type_;
   12478   parameter_count_ = other->parameter_count_;
   12479   local_count_ = other->local_count_;
   12480   if (other->outer_ != NULL) outer_ = other->outer_->Copy();  // Deep copy.
   12481   entry_ = other->entry_;
   12482   pop_count_ = other->pop_count_;
   12483   push_count_ = other->push_count_;
   12484   specials_count_ = other->specials_count_;
   12485   ast_id_ = other->ast_id_;
   12486 }
   12487 
   12488 
   12489 void HEnvironment::AddIncomingEdge(HBasicBlock* block, HEnvironment* other) {
   12490   DCHECK(!block->IsLoopHeader());
   12491   DCHECK(values_.length() == other->values_.length());
   12492 
   12493   int length = values_.length();
   12494   for (int i = 0; i < length; ++i) {
   12495     HValue* value = values_[i];
   12496     if (value != NULL && value->IsPhi() && value->block() == block) {
   12497       // There is already a phi for the i'th value.
   12498       HPhi* phi = HPhi::cast(value);
   12499       // Assert index is correct and that we haven't missed an incoming edge.
   12500       DCHECK(phi->merged_index() == i || !phi->HasMergedIndex());
   12501       DCHECK(phi->OperandCount() == block->predecessors()->length());
   12502       phi->AddInput(other->values_[i]);
   12503     } else if (values_[i] != other->values_[i]) {
   12504       // There is a fresh value on the incoming edge, a phi is needed.
   12505       DCHECK(values_[i] != NULL && other->values_[i] != NULL);
   12506       HPhi* phi = block->AddNewPhi(i);
   12507       HValue* old_value = values_[i];
   12508       for (int j = 0; j < block->predecessors()->length(); j++) {
   12509         phi->AddInput(old_value);
   12510       }
   12511       phi->AddInput(other->values_[i]);
   12512       this->values_[i] = phi;
   12513     }
   12514   }
   12515 }
   12516 
   12517 
   12518 void HEnvironment::Bind(int index, HValue* value) {
   12519   DCHECK(value != NULL);
   12520   assigned_variables_.Add(index, zone());
   12521   values_[index] = value;
   12522 }
   12523 
   12524 
   12525 bool HEnvironment::HasExpressionAt(int index) const {
   12526   return index >= parameter_count_ + specials_count_ + local_count_;
   12527 }
   12528 
   12529 
   12530 bool HEnvironment::ExpressionStackIsEmpty() const {
   12531   DCHECK(length() >= first_expression_index());
   12532   return length() == first_expression_index();
   12533 }
   12534 
   12535 
   12536 void HEnvironment::SetExpressionStackAt(int index_from_top, HValue* value) {
   12537   int count = index_from_top + 1;
   12538   int index = values_.length() - count;
   12539   DCHECK(HasExpressionAt(index));
   12540   // The push count must include at least the element in question or else
   12541   // the new value will not be included in this environment's history.
   12542   if (push_count_ < count) {
   12543     // This is the same effect as popping then re-pushing 'count' elements.
   12544     pop_count_ += (count - push_count_);
   12545     push_count_ = count;
   12546   }
   12547   values_[index] = value;
   12548 }
   12549 
   12550 
   12551 HValue* HEnvironment::RemoveExpressionStackAt(int index_from_top) {
   12552   int count = index_from_top + 1;
   12553   int index = values_.length() - count;
   12554   DCHECK(HasExpressionAt(index));
   12555   // Simulate popping 'count' elements and then
   12556   // pushing 'count - 1' elements back.
   12557   pop_count_ += Max(count - push_count_, 0);
   12558   push_count_ = Max(push_count_ - count, 0) + (count - 1);
   12559   return values_.Remove(index);
   12560 }
   12561 
   12562 
   12563 void HEnvironment::Drop(int count) {
   12564   for (int i = 0; i < count; ++i) {
   12565     Pop();
   12566   }
   12567 }
   12568 
   12569 
   12570 void HEnvironment::Print() const {
   12571   OFStream os(stdout);
   12572   os << *this << "\n";
   12573 }
   12574 
   12575 
   12576 HEnvironment* HEnvironment::Copy() const {
   12577   return new(zone()) HEnvironment(this, zone());
   12578 }
   12579 
   12580 
   12581 HEnvironment* HEnvironment::CopyWithoutHistory() const {
   12582   HEnvironment* result = Copy();
   12583   result->ClearHistory();
   12584   return result;
   12585 }
   12586 
   12587 
   12588 HEnvironment* HEnvironment::CopyAsLoopHeader(HBasicBlock* loop_header) const {
   12589   HEnvironment* new_env = Copy();
   12590   for (int i = 0; i < values_.length(); ++i) {
   12591     HPhi* phi = loop_header->AddNewPhi(i);
   12592     phi->AddInput(values_[i]);
   12593     new_env->values_[i] = phi;
   12594   }
   12595   new_env->ClearHistory();
   12596   return new_env;
   12597 }
   12598 
   12599 
   12600 HEnvironment* HEnvironment::CreateStubEnvironment(HEnvironment* outer,
   12601                                                   Handle<JSFunction> target,
   12602                                                   FrameType frame_type,
   12603                                                   int arguments) const {
   12604   HEnvironment* new_env =
   12605       new(zone()) HEnvironment(outer, target, frame_type,
   12606                                arguments + 1, zone());
   12607   for (int i = 0; i <= arguments; ++i) {  // Include receiver.
   12608     new_env->Push(ExpressionStackAt(arguments - i));
   12609   }
   12610   new_env->ClearHistory();
   12611   return new_env;
   12612 }
   12613 
   12614 void HEnvironment::MarkAsTailCaller() {
   12615   DCHECK_EQ(JS_FUNCTION, frame_type());
   12616   frame_type_ = TAIL_CALLER_FUNCTION;
   12617 }
   12618 
   12619 void HEnvironment::ClearTailCallerMark() {
   12620   DCHECK_EQ(TAIL_CALLER_FUNCTION, frame_type());
   12621   frame_type_ = JS_FUNCTION;
   12622 }
   12623 
   12624 HEnvironment* HEnvironment::CopyForInlining(
   12625     Handle<JSFunction> target, int arguments, FunctionLiteral* function,
   12626     HConstant* undefined, InliningKind inlining_kind,
   12627     TailCallMode syntactic_tail_call_mode) const {
   12628   DCHECK_EQ(JS_FUNCTION, frame_type());
   12629 
   12630   // Outer environment is a copy of this one without the arguments.
   12631   int arity = function->scope()->num_parameters();
   12632 
   12633   HEnvironment* outer = Copy();
   12634   outer->Drop(arguments + 1);  // Including receiver.
   12635   outer->ClearHistory();
   12636 
   12637   if (syntactic_tail_call_mode == TailCallMode::kAllow) {
   12638     DCHECK_EQ(NORMAL_RETURN, inlining_kind);
   12639     outer->MarkAsTailCaller();
   12640   }
   12641 
   12642   if (inlining_kind == CONSTRUCT_CALL_RETURN) {
   12643     // Create artificial constructor stub environment.  The receiver should
   12644     // actually be the constructor function, but we pass the newly allocated
   12645     // object instead, DoComputeConstructStubFrame() relies on that.
   12646     outer = CreateStubEnvironment(outer, target, JS_CONSTRUCT, arguments);
   12647   } else if (inlining_kind == GETTER_CALL_RETURN) {
   12648     // We need an additional StackFrame::INTERNAL frame for restoring the
   12649     // correct context.
   12650     outer = CreateStubEnvironment(outer, target, JS_GETTER, arguments);
   12651   } else if (inlining_kind == SETTER_CALL_RETURN) {
   12652     // We need an additional StackFrame::INTERNAL frame for temporarily saving
   12653     // the argument of the setter, see StoreStubCompiler::CompileStoreViaSetter.
   12654     outer = CreateStubEnvironment(outer, target, JS_SETTER, arguments);
   12655   }
   12656 
   12657   if (arity != arguments) {
   12658     // Create artificial arguments adaptation environment.
   12659     outer = CreateStubEnvironment(outer, target, ARGUMENTS_ADAPTOR, arguments);
   12660   }
   12661 
   12662   HEnvironment* inner =
   12663       new(zone()) HEnvironment(outer, function->scope(), target, zone());
   12664   // Get the argument values from the original environment.
   12665   for (int i = 0; i <= arity; ++i) {  // Include receiver.
   12666     HValue* push = (i <= arguments) ?
   12667         ExpressionStackAt(arguments - i) : undefined;
   12668     inner->SetValueAt(i, push);
   12669   }
   12670   inner->SetValueAt(arity + 1, context());
   12671   for (int i = arity + 2; i < inner->length(); ++i) {
   12672     inner->SetValueAt(i, undefined);
   12673   }
   12674 
   12675   inner->set_ast_id(BailoutId::FunctionEntry());
   12676   return inner;
   12677 }
   12678 
   12679 
   12680 std::ostream& operator<<(std::ostream& os, const HEnvironment& env) {
   12681   for (int i = 0; i < env.length(); i++) {
   12682     if (i == 0) os << "parameters\n";
   12683     if (i == env.parameter_count()) os << "specials\n";
   12684     if (i == env.parameter_count() + env.specials_count()) os << "locals\n";
   12685     if (i == env.parameter_count() + env.specials_count() + env.local_count()) {
   12686       os << "expressions\n";
   12687     }
   12688     HValue* val = env.values()->at(i);
   12689     os << i << ": ";
   12690     if (val != NULL) {
   12691       os << val;
   12692     } else {
   12693       os << "NULL";
   12694     }
   12695     os << "\n";
   12696   }
   12697   return os << "\n";
   12698 }
   12699 
   12700 
   12701 void HTracer::TraceCompilation(CompilationInfo* info) {
   12702   Tag tag(this, "compilation");
   12703   std::string name;
   12704   if (info->parse_info()) {
   12705     Object* source_name = info->script()->name();
   12706     if (source_name->IsString()) {
   12707       String* str = String::cast(source_name);
   12708       if (str->length() > 0) {
   12709         name.append(str->ToCString().get());
   12710         name.append(":");
   12711       }
   12712     }
   12713   }
   12714   std::unique_ptr<char[]> method_name = info->GetDebugName();
   12715   name.append(method_name.get());
   12716   if (info->IsOptimizing()) {
   12717     PrintStringProperty("name", name.c_str());
   12718     PrintIndent();
   12719     trace_.Add("method \"%s:%d\"\n", method_name.get(),
   12720                info->optimization_id());
   12721   } else {
   12722     PrintStringProperty("name", name.c_str());
   12723     PrintStringProperty("method", "stub");
   12724   }
   12725   PrintLongProperty("date",
   12726                     static_cast<int64_t>(base::OS::TimeCurrentMillis()));
   12727 }
   12728 
   12729 
   12730 void HTracer::TraceLithium(const char* name, LChunk* chunk) {
   12731   DCHECK(!chunk->isolate()->concurrent_recompilation_enabled());
   12732   AllowHandleDereference allow_deref;
   12733   AllowDeferredHandleDereference allow_deferred_deref;
   12734   Trace(name, chunk->graph(), chunk);
   12735 }
   12736 
   12737 
   12738 void HTracer::TraceHydrogen(const char* name, HGraph* graph) {
   12739   DCHECK(!graph->isolate()->concurrent_recompilation_enabled());
   12740   AllowHandleDereference allow_deref;
   12741   AllowDeferredHandleDereference allow_deferred_deref;
   12742   Trace(name, graph, NULL);
   12743 }
   12744 
   12745 
   12746 void HTracer::Trace(const char* name, HGraph* graph, LChunk* chunk) {
   12747   Tag tag(this, "cfg");
   12748   PrintStringProperty("name", name);
   12749   const ZoneList<HBasicBlock*>* blocks = graph->blocks();
   12750   for (int i = 0; i < blocks->length(); i++) {
   12751     HBasicBlock* current = blocks->at(i);
   12752     Tag block_tag(this, "block");
   12753     PrintBlockProperty("name", current->block_id());
   12754     PrintIntProperty("from_bci", -1);
   12755     PrintIntProperty("to_bci", -1);
   12756 
   12757     if (!current->predecessors()->is_empty()) {
   12758       PrintIndent();
   12759       trace_.Add("predecessors");
   12760       for (int j = 0; j < current->predecessors()->length(); ++j) {
   12761         trace_.Add(" \"B%d\"", current->predecessors()->at(j)->block_id());
   12762       }
   12763       trace_.Add("\n");
   12764     } else {
   12765       PrintEmptyProperty("predecessors");
   12766     }
   12767 
   12768     if (current->end()->SuccessorCount() == 0) {
   12769       PrintEmptyProperty("successors");
   12770     } else  {
   12771       PrintIndent();
   12772       trace_.Add("successors");
   12773       for (HSuccessorIterator it(current->end()); !it.Done(); it.Advance()) {
   12774         trace_.Add(" \"B%d\"", it.Current()->block_id());
   12775       }
   12776       trace_.Add("\n");
   12777     }
   12778 
   12779     PrintEmptyProperty("xhandlers");
   12780 
   12781     {
   12782       PrintIndent();
   12783       trace_.Add("flags");
   12784       if (current->IsLoopSuccessorDominator()) {
   12785         trace_.Add(" \"dom-loop-succ\"");
   12786       }
   12787       if (current->IsUnreachable()) {
   12788         trace_.Add(" \"dead\"");
   12789       }
   12790       if (current->is_osr_entry()) {
   12791         trace_.Add(" \"osr\"");
   12792       }
   12793       trace_.Add("\n");
   12794     }
   12795 
   12796     if (current->dominator() != NULL) {
   12797       PrintBlockProperty("dominator", current->dominator()->block_id());
   12798     }
   12799 
   12800     PrintIntProperty("loop_depth", current->LoopNestingDepth());
   12801 
   12802     if (chunk != NULL) {
   12803       int first_index = current->first_instruction_index();
   12804       int last_index = current->last_instruction_index();
   12805       PrintIntProperty(
   12806           "first_lir_id",
   12807           LifetimePosition::FromInstructionIndex(first_index).Value());
   12808       PrintIntProperty(
   12809           "last_lir_id",
   12810           LifetimePosition::FromInstructionIndex(last_index).Value());
   12811     }
   12812 
   12813     {
   12814       Tag states_tag(this, "states");
   12815       Tag locals_tag(this, "locals");
   12816       int total = current->phis()->length();
   12817       PrintIntProperty("size", current->phis()->length());
   12818       PrintStringProperty("method", "None");
   12819       for (int j = 0; j < total; ++j) {
   12820         HPhi* phi = current->phis()->at(j);
   12821         PrintIndent();
   12822         std::ostringstream os;
   12823         os << phi->merged_index() << " " << NameOf(phi) << " " << *phi << "\n";
   12824         trace_.Add(os.str().c_str());
   12825       }
   12826     }
   12827 
   12828     {
   12829       Tag HIR_tag(this, "HIR");
   12830       for (HInstructionIterator it(current); !it.Done(); it.Advance()) {
   12831         HInstruction* instruction = it.Current();
   12832         int uses = instruction->UseCount();
   12833         PrintIndent();
   12834         std::ostringstream os;
   12835         os << "0 " << uses << " " << NameOf(instruction) << " " << *instruction;
   12836         if (instruction->has_position()) {
   12837           const SourcePosition pos = instruction->position();
   12838           os << " pos:";
   12839           if (pos.isInlined()) os << "inlining(" << pos.InliningId() << "),";
   12840           os << pos.ScriptOffset();
   12841         }
   12842         os << " <|@\n";
   12843         trace_.Add(os.str().c_str());
   12844       }
   12845     }
   12846 
   12847 
   12848     if (chunk != NULL) {
   12849       Tag LIR_tag(this, "LIR");
   12850       int first_index = current->first_instruction_index();
   12851       int last_index = current->last_instruction_index();
   12852       if (first_index != -1 && last_index != -1) {
   12853         const ZoneList<LInstruction*>* instructions = chunk->instructions();
   12854         for (int i = first_index; i <= last_index; ++i) {
   12855           LInstruction* linstr = instructions->at(i);
   12856           if (linstr != NULL) {
   12857             PrintIndent();
   12858             trace_.Add("%d ",
   12859                        LifetimePosition::FromInstructionIndex(i).Value());
   12860             linstr->PrintTo(&trace_);
   12861             std::ostringstream os;
   12862             os << " [hir:" << NameOf(linstr->hydrogen_value()) << "] <|@\n";
   12863             trace_.Add(os.str().c_str());
   12864           }
   12865         }
   12866       }
   12867     }
   12868   }
   12869 }
   12870 
   12871 
   12872 void HTracer::TraceLiveRanges(const char* name, LAllocator* allocator) {
   12873   Tag tag(this, "intervals");
   12874   PrintStringProperty("name", name);
   12875 
   12876   const Vector<LiveRange*>* fixed_d = allocator->fixed_double_live_ranges();
   12877   for (int i = 0; i < fixed_d->length(); ++i) {
   12878     TraceLiveRange(fixed_d->at(i), "fixed", allocator->zone());
   12879   }
   12880 
   12881   const Vector<LiveRange*>* fixed = allocator->fixed_live_ranges();
   12882   for (int i = 0; i < fixed->length(); ++i) {
   12883     TraceLiveRange(fixed->at(i), "fixed", allocator->zone());
   12884   }
   12885 
   12886   const ZoneList<LiveRange*>* live_ranges = allocator->live_ranges();
   12887   for (int i = 0; i < live_ranges->length(); ++i) {
   12888     TraceLiveRange(live_ranges->at(i), "object", allocator->zone());
   12889   }
   12890 }
   12891 
   12892 
   12893 void HTracer::TraceLiveRange(LiveRange* range, const char* type,
   12894                              Zone* zone) {
   12895   if (range != NULL && !range->IsEmpty()) {
   12896     PrintIndent();
   12897     trace_.Add("%d %s", range->id(), type);
   12898     if (range->HasRegisterAssigned()) {
   12899       LOperand* op = range->CreateAssignedOperand(zone);
   12900       int assigned_reg = op->index();
   12901       if (op->IsDoubleRegister()) {
   12902         trace_.Add(" \"%s\"",
   12903                    GetRegConfig()->GetDoubleRegisterName(assigned_reg));
   12904       } else {
   12905         DCHECK(op->IsRegister());
   12906         trace_.Add(" \"%s\"",
   12907                    GetRegConfig()->GetGeneralRegisterName(assigned_reg));
   12908       }
   12909     } else if (range->IsSpilled()) {
   12910       LOperand* op = range->TopLevel()->GetSpillOperand();
   12911       if (op->IsDoubleStackSlot()) {
   12912         trace_.Add(" \"double_stack:%d\"", op->index());
   12913       } else {
   12914         DCHECK(op->IsStackSlot());
   12915         trace_.Add(" \"stack:%d\"", op->index());
   12916       }
   12917     }
   12918     int parent_index = -1;
   12919     if (range->IsChild()) {
   12920       parent_index = range->parent()->id();
   12921     } else {
   12922       parent_index = range->id();
   12923     }
   12924     LOperand* op = range->FirstHint();
   12925     int hint_index = -1;
   12926     if (op != NULL && op->IsUnallocated()) {
   12927       hint_index = LUnallocated::cast(op)->virtual_register();
   12928     }
   12929     trace_.Add(" %d %d", parent_index, hint_index);
   12930     UseInterval* cur_interval = range->first_interval();
   12931     while (cur_interval != NULL && range->Covers(cur_interval->start())) {
   12932       trace_.Add(" [%d, %d[",
   12933                  cur_interval->start().Value(),
   12934                  cur_interval->end().Value());
   12935       cur_interval = cur_interval->next();
   12936     }
   12937 
   12938     UsePosition* current_pos = range->first_pos();
   12939     while (current_pos != NULL) {
   12940       if (current_pos->RegisterIsBeneficial() || FLAG_trace_all_uses) {
   12941         trace_.Add(" %d M", current_pos->pos().Value());
   12942       }
   12943       current_pos = current_pos->next();
   12944     }
   12945 
   12946     trace_.Add(" \"\"\n");
   12947   }
   12948 }
   12949 
   12950 
   12951 void HTracer::FlushToFile() {
   12952   AppendChars(filename_.start(), trace_.ToCString().get(), trace_.length(),
   12953               false);
   12954   trace_.Reset();
   12955 }
   12956 
   12957 
   12958 void HStatistics::Initialize(CompilationInfo* info) {
   12959   if (!info->has_shared_info()) return;
   12960   source_size_ += info->shared_info()->SourceSize();
   12961 }
   12962 
   12963 
   12964 void HStatistics::Print() {
   12965   PrintF(
   12966       "\n"
   12967       "----------------------------------------"
   12968       "----------------------------------------\n"
   12969       "--- Hydrogen timing results:\n"
   12970       "----------------------------------------"
   12971       "----------------------------------------\n");
   12972   base::TimeDelta sum;
   12973   for (int i = 0; i < times_.length(); ++i) {
   12974     sum += times_[i];
   12975   }
   12976 
   12977   for (int i = 0; i < names_.length(); ++i) {
   12978     PrintF("%33s", names_[i]);
   12979     double ms = times_[i].InMillisecondsF();
   12980     double percent = times_[i].PercentOf(sum);
   12981     PrintF(" %8.3f ms / %4.1f %% ", ms, percent);
   12982 
   12983     size_t size = sizes_[i];
   12984     double size_percent = static_cast<double>(size) * 100 / total_size_;
   12985     PrintF(" %9zu bytes / %4.1f %%\n", size, size_percent);
   12986   }
   12987 
   12988   PrintF(
   12989       "----------------------------------------"
   12990       "----------------------------------------\n");
   12991   base::TimeDelta total = create_graph_ + optimize_graph_ + generate_code_;
   12992   PrintF("%33s %8.3f ms / %4.1f %% \n", "Create graph",
   12993          create_graph_.InMillisecondsF(), create_graph_.PercentOf(total));
   12994   PrintF("%33s %8.3f ms / %4.1f %% \n", "Optimize graph",
   12995          optimize_graph_.InMillisecondsF(), optimize_graph_.PercentOf(total));
   12996   PrintF("%33s %8.3f ms / %4.1f %% \n", "Generate and install code",
   12997          generate_code_.InMillisecondsF(), generate_code_.PercentOf(total));
   12998   PrintF(
   12999       "----------------------------------------"
   13000       "----------------------------------------\n");
   13001   PrintF("%33s %8.3f ms           %9zu bytes\n", "Total",
   13002          total.InMillisecondsF(), total_size_);
   13003   PrintF("%33s     (%.1f times slower than full code gen)\n", "",
   13004          total.TimesOf(full_code_gen_));
   13005 
   13006   double source_size_in_kb = static_cast<double>(source_size_) / 1024;
   13007   double normalized_time =  source_size_in_kb > 0
   13008       ? total.InMillisecondsF() / source_size_in_kb
   13009       : 0;
   13010   double normalized_size_in_kb =
   13011       source_size_in_kb > 0
   13012           ? static_cast<double>(total_size_) / 1024 / source_size_in_kb
   13013           : 0;
   13014   PrintF("%33s %8.3f ms           %7.3f kB allocated\n",
   13015          "Average per kB source", normalized_time, normalized_size_in_kb);
   13016 }
   13017 
   13018 
   13019 void HStatistics::SaveTiming(const char* name, base::TimeDelta time,
   13020                              size_t size) {
   13021   total_size_ += size;
   13022   for (int i = 0; i < names_.length(); ++i) {
   13023     if (strcmp(names_[i], name) == 0) {
   13024       times_[i] += time;
   13025       sizes_[i] += size;
   13026       return;
   13027     }
   13028   }
   13029   names_.Add(name);
   13030   times_.Add(time);
   13031   sizes_.Add(size);
   13032 }
   13033 
   13034 
   13035 HPhase::~HPhase() {
   13036   if (ShouldProduceTraceOutput()) {
   13037     isolate()->GetHTracer()->TraceHydrogen(name(), graph_);
   13038   }
   13039 
   13040 #ifdef DEBUG
   13041   graph_->Verify(false);  // No full verify.
   13042 #endif
   13043 }
   13044 
   13045 }  // namespace internal
   13046 }  // namespace v8
   13047